Merge "Expose constants in Telephony.Carriers"
diff --git a/Android.bp b/Android.bp
index 0c17fa7..9411eec 100644
--- a/Android.bp
+++ b/Android.bp
@@ -297,6 +297,8 @@
     ],
 }
 
+// AIDL files under these paths are mixture of public and private ones.
+// They shouldn't be exported across module boundaries.
 java_defaults {
     name: "framework-aidl-export-defaults",
     aidl: {
@@ -321,12 +323,6 @@
             "wifi/aidl-export",
         ],
     },
-
-    required: [
-        // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly.
-        "gps_debug.conf",
-	"protolog.conf.json.gz",
-    ],
 }
 
 // Collection of classes that are generated from non-Java files that are not listed in
@@ -344,6 +340,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",
@@ -416,6 +413,12 @@
         "view-inspector-annotation-processor",
         "staledataclass-annotation-processor",
     ],
+
+    required: [
+        // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly.
+        "gps_debug.conf",
+        "protolog.conf.json.gz",
+    ],
 }
 
 filegroup {
@@ -539,7 +542,6 @@
 
 java_library {
     name: "framework-annotation-proc",
-    defaults: ["framework-aidl-export-defaults"],
     srcs: [":framework-all-sources"],
     libs: [
         "app-compat-annotations",
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 fd20186..0000000
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearch.java
+++ /dev/null
@@ -1,806 +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);
-        }
-
-        /**
-         * 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 e3f6b3d..39abe78 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -18,14 +18,15 @@
 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;
 
 import com.android.internal.infra.AndroidFuture;
 
+import com.google.android.icing.proto.DocumentProto;
 import com.google.android.icing.proto.SchemaProto;
 import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SearchSpecProto;
 import com.google.android.icing.proto.StatusProto;
 import com.google.android.icing.protobuf.InvalidProtocolBufferException;
 
@@ -149,25 +150,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<>();
@@ -180,34 +182,81 @@
     }
 
     /**
+     * Retrieves {@link android.app.appsearch.AppSearch.Document}s by URI.
+     *
+     * <p>You should not call this method directly; instead, use the
+     * {@code AppSearch#getDocuments()} API provided by JetPack.
+     *
+     * @param uris URIs of the documents to look up.
+     * @param executor Executor on which to invoke the callback.
+     * @param callback Callback to receive the documents or error.
+     */
+    public void getDocuments(
+            @NonNull List<String> uris,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull BiConsumer<List<AppSearch.Document>, ? super Throwable> callback) {
+        AndroidFuture<List<byte[]>> future = new AndroidFuture<>();
+        future.whenCompleteAsync((documentProtos, err) -> {
+            if (err != null) {
+                callback.accept(null, err);
+                return;
+            }
+            if (documentProtos != null) {
+                List<AppSearch.Document> results = new ArrayList<>(documentProtos.size());
+                for (int i = 0; i < documentProtos.size(); i++) {
+                    DocumentProto documentProto;
+                    try {
+                        documentProto = DocumentProto.parseFrom(documentProtos.get(i));
+                    } catch (InvalidProtocolBufferException e) {
+                        callback.accept(null, e);
+                        return;
+                    }
+                    results.add(new AppSearch.Document(documentProto));
+                }
+                callback.accept(results, null);
+                return;
+            }
+            // Nothing was supplied in the future at all
+            callback.accept(null, new IllegalStateException(
+                    "Unknown failure occurred while retrieving documents"));
+        }, executor);
+        // TODO(b/146386470) stream uris?
+        try {
+            mService.getDocuments(uris.toArray(new String[uris.size()]), future);
+        } catch (RemoteException e) {
+            future.completeExceptionally(e);
+        }
+    }
+
+    /**
      * This method searches for documents based on a given query string. It also accepts
      * specifications regarding how to search and format the results.
      *
      *<p>Currently we support following features in the raw query format:
      * <ul>
      *     <li>AND
-     *     AND joins (e.g. “match documents that have both the terms ‘dog’ and
+     *     <p>AND joins (e.g. “match documents that have both the terms ‘dog’ and
      *     ‘cat’”).
      *     Example: hello world matches documents that have both ‘hello’ and ‘world’
      *     <li>OR
-     *     OR joins (e.g. “match documents that have either the term ‘dog’ or
+     *     <p>OR joins (e.g. “match documents that have either the term ‘dog’ or
      *     ‘cat’”).
      *     Example: dog OR puppy
      *     <li>Exclusion
-     *     Exclude a term (e.g. “match documents that do
+     *     <p>Exclude a term (e.g. “match documents that do
      *     not have the term ‘dog’”).
      *     Example: -dog excludes the term ‘dog’
      *     <li>Grouping terms
-     *     Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
+     *     <p>Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
      *     “match documents that have either ‘dog’ or ‘puppy’, and either ‘cat’ or ‘kitten’”).
      *     Example: (dog puppy) (cat kitten) two one group containing two terms.
      *     <li>Property restricts
-     *      which properties of a document to specifically match terms in (e.g.
+     *     <p> Specifies which properties of a document to specifically match terms in (e.g.
      *     “match documents where the ‘subject’ property contains ‘important’”).
      *     Example: subject:important matches documents with the term ‘important’ in the
      *     ‘subject’ property
      *     <li>Schema type restricts
-     *     This is similar to property restricts, but allows for restricts on top-level document
+     *     <p>This is similar to property restricts, but allows for restricts on top-level document
      *     fields, such as schema_type. Clients should be able to limit their query to documents of
      *     a certain schema_type (e.g. “match documents that are of the ‘Email’ schema_type”).
      *     Example: { schema_type_filters: “Email”, “Video”,query: “dog” } will match documents
@@ -236,7 +285,6 @@
                 callback.accept(null, err);
                 return;
             }
-
             if (searchResultBytes != null) {
                 SearchResultProto searchResultProto;
                 try {
@@ -256,14 +304,16 @@
                 callback.accept(searchResults, null);
                 return;
             }
-
             // Nothing was supplied in the future at all
             callback.accept(
                     null, new IllegalStateException("Unknown failure occurred while querying"));
         }, executor);
-
         try {
-            mService.query(queryExpression, searchSpec.getProto().toByteArray(), future);
+            SearchSpecProto searchSpecProto = searchSpec.getSearchSpecProto();
+            searchSpecProto = searchSpecProto.toBuilder().setQuery(queryExpression).build();
+            mService.query(searchSpecProto.toByteArray(),
+                    searchSpec.getResultSpecProto().toByteArray(),
+                    searchSpec.getScoringSpecProto().toByteArray(), future);
         } catch (RemoteException e) {
             future.completeExceptionally(e);
         }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 20c8af98..b800825 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -47,12 +47,24 @@
     void putDocuments(in List documentsBytes, in AndroidFuture<AppSearchBatchResult> callback);
 
     /**
-     * Searches a document based on a given query string.
+     * Retrieves documents from the index.
      *
-     * @param queryExpression Query String to search.
-     * @param searchSpec Serialized SearchSpecProto.
+     * @param uris The URIs of the documents to retrieve
+     * @param callback {@link AndroidFuture}&lt;{@link List}&lt;byte[]&gt;&gt;. Will be completed
+     *     with a {@link List} containing serialized DocumentProtos, or completed exceptionally if
+     *     get fails.
+     */
+    void getDocuments(in String[] uris, in AndroidFuture callback);
+
+    /**
+     * Searches a document based on a given specifications.
+     *
+     * @param searchSpecBytes Serialized SearchSpecProto.
+     * @param resultSpecBytes Serialized SearchResultsProto.
+     * @param scoringSpecBytes Serialized ScoringSpecProto.
      * @param callback {@link AndroidFuture}. Will be completed with a serialized
      *     {@link SearchResultsProto}, or completed exceptionally if query fails.
      */
-     void query(in String queryExpression, in byte[] searchSpecBytes, in AndroidFuture callback);
+    void query(in byte[] searchSpecBytes, in byte[] resultSpecBytes,
+            in byte[] scoringSpecBytes, in AndroidFuture callback);
 }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java b/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.java
new file mode 100644
index 0000000..5ce2960
--- /dev/null
+++ b/apex/appsearch/framework/java/android/app/appsearch/MatchInfo.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 android.app.appsearch;
+
+import android.annotation.NonNull;
+import android.util.Range;
+
+import com.google.android.icing.proto.SnippetMatchProto;
+
+/**
+ * Snippet: It refers to a substring of text from the content of document that is returned as a
+ * part of search result.
+ * This class represents a match objects for any Snippets that might be present in
+ * {@link SearchResults} from query. Using this class user can get the full text, exact matches and
+ * Snippets of document content for a given match.
+ *
+ * <p>Class Example 1:
+ * A document contains following text in property subject:
+ * <p>A commonly used fake word is foo. Another nonsense word that’s used a lot is bar.
+ *
+ * <p>If the queryExpression is "foo".
+ *
+ * <p>{@link MatchInfo#getPropertyPath()} returns "subject"
+ * <p>{@link MatchInfo#getFullText()} returns "A commonly used fake word is foo. Another nonsense
+ * word that’s used a lot is bar."
+ * <p>{@link MatchInfo#getExactMatchPosition()} returns [29, 32]
+ * <p>{@link MatchInfo#getExactMatch()} returns "foo"
+ * <p>{@link MatchInfo#getSnippetPosition()} returns [29, 41]
+ * <p>{@link MatchInfo#getSnippet()} returns "is foo. Another"
+ * <p>
+ * <p>Class Example 2:
+ * A document contains a property name sender which contains 2 property names name and email, so
+ * we will have 2 property paths: {@code sender.name} and {@code sender.email}.
+ * <p> Let {@code sender.name = "Test Name Jr."} and {@code sender.email = "TestNameJr@gmail.com"}
+ *
+ * <p>If the queryExpression is "Test". We will have 2 matches.
+ *
+ * <p> Match-1
+ * <p>{@link MatchInfo#getPropertyPath()} returns "sender.name"
+ * <p>{@link MatchInfo#getFullText()} returns "Test Name Jr."
+ * <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 4]
+ * <p>{@link MatchInfo#getExactMatch()} returns "Test"
+ * <p>{@link MatchInfo#getSnippetPosition()} returns [0, 9]
+ * <p>{@link MatchInfo#getSnippet()} returns "Test Name Jr."
+ * <p> Match-2
+ * <p>{@link MatchInfo#getPropertyPath()} returns "sender.email"
+ * <p>{@link MatchInfo#getFullText()} returns "TestNameJr@gmail.com"
+ * <p>{@link MatchInfo#getExactMatchPosition()} returns [0, 20]
+ * <p>{@link MatchInfo#getExactMatch()} returns "TestNameJr@gmail.com"
+ * <p>{@link MatchInfo#getSnippetPosition()} returns [0, 20]
+ * <p>{@link MatchInfo#getSnippet()} returns "TestNameJr@gmail.com"
+ * @hide
+ */
+// TODO(sidchhabra): Capture real snippet after integration with icingLib.
+public final class MatchInfo {
+
+    private final String mPropertyPath;
+    private final SnippetMatchProto mSnippetMatch;
+    private final AppSearchDocument mDocument;
+    /**
+     * List of content with same property path in a document when there are multiple matches in
+     * repeated sections.
+     */
+    private final String[] mValues;
+
+    /** @hide */
+    public MatchInfo(@NonNull String propertyPath, @NonNull SnippetMatchProto snippetMatch,
+            @NonNull AppSearchDocument document) {
+        mPropertyPath = propertyPath;
+        mSnippetMatch = snippetMatch;
+        mDocument = document;
+        // In IcingLib snippeting is available for only 3 data types i.e String, double and long,
+        // so we need to check which of these three are requested.
+        // TODO (sidchhabra): getPropertyStringArray takes property name, handle for property path.
+        String[] values = mDocument.getPropertyStringArray(propertyPath);
+        if (values == null) {
+            values = doubleToString(mDocument.getPropertyDoubleArray(propertyPath));
+        }
+        if (values == null) {
+            values = longToString(mDocument.getPropertyLongArray(propertyPath));
+        }
+        if (values == null) {
+            throw new IllegalStateException("No content found for requested property path!");
+        }
+        mValues = values;
+    }
+
+    /**
+     * Gets the property path corresponding to the given entry.
+     * <p>Property Path: '.' - delimited sequence of property names indicating which property in
+     * the Document these snippets correspond to.
+     * <p>Example properties: 'body', 'sender.name', 'sender.emailaddress', etc.
+     * For class example 1 this returns "subject"
+     */
+    @NonNull
+    public String getPropertyPath() {
+        return mPropertyPath;
+    }
+
+    /**
+     * Gets the full text corresponding to the given entry.
+     * <p>For class example this returns "A commonly used fake word is foo. Another nonsense word
+     * that’s used a lot is bar."
+     */
+    @NonNull
+    public String getFullText() {
+        return mValues[mSnippetMatch.getValuesIndex()];
+    }
+
+    /**
+     * Gets the exact match range corresponding to the given entry.
+     * <p>For class example 1 this returns [29, 32]
+     */
+    @NonNull
+    public Range getExactMatchPosition() {
+        return new Range(mSnippetMatch.getExactMatchPosition(),
+                mSnippetMatch.getExactMatchPosition() + mSnippetMatch.getExactMatchBytes());
+    }
+
+    /**
+     * Gets the exact match corresponding to the given entry.
+     * <p>For class example 1 this returns "foo"
+     */
+    @NonNull
+    public CharSequence getExactMatch() {
+        return getSubstring(getExactMatchPosition());
+    }
+
+    /**
+     * Gets the snippet range corresponding to the given entry.
+     * <p>For class example 1 this returns [29, 41]
+     */
+    @NonNull
+    public Range getSnippetPosition() {
+        return new Range(mSnippetMatch.getWindowPosition(),
+                mSnippetMatch.getWindowPosition() + mSnippetMatch.getWindowBytes());
+    }
+
+    /**
+     * Gets the snippet corresponding to the given entry.
+     * <p>Snippet - Provides a subset of the content to display. The
+     * length of this content can be changed {@link SearchSpec.Builder#setMaxSnippetSize(int)}.
+     * Windowing is centered around the middle of the matched token with content on either side
+     * clipped to token boundaries.
+     * <p>For class example 1 this returns "foo. Another"
+     */
+    @NonNull
+    public CharSequence getSnippet() {
+        return getSubstring(getSnippetPosition());
+    }
+
+    private CharSequence getSubstring(Range range) {
+        return getFullText()
+                .substring((int) range.getLower(), (int) range.getUpper());
+    }
+
+    /** Utility method to convert double[] to String[] */
+    private String[] doubleToString(double[] values) {
+        //TODO(sidchhabra): Implement the method.
+        return null;
+    }
+
+    /** Utility method to convert long[] to String[] */
+    private String[] longToString(long[] values) {
+        //TODO(sidchhabra): Implement the method.
+        return null;
+    }
+}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index d763103..7287fe6 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -17,27 +17,51 @@
 package android.app.appsearch;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SnippetMatchProto;
+import com.google.android.icing.proto.SnippetProto;
 
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 /**
  * SearchResults are a list of results that are returned from a query. Each result from this
  * list contains a document and may contain other fields like snippets based on request.
+ * This iterator class is not thread safe.
  * @hide
  */
-public final class SearchResults {
+public final class SearchResults implements Iterator<SearchResults.Result> {
 
     private final SearchResultProto mSearchResultProto;
+    private int mNextIdx;
 
     /** @hide */
     public SearchResults(SearchResultProto searchResultProto) {
         mSearchResultProto = searchResultProto;
     }
 
+    @Override
+    public boolean hasNext() {
+        return mNextIdx < mSearchResultProto.getResultsCount();
+    }
+
+    @NonNull
+    @Override
+    public Result next() {
+        if (!hasNext()) {
+            throw new NoSuchElementException();
+        }
+        Result result = new Result(mSearchResultProto.getResults(mNextIdx));
+        mNextIdx++;
+        return result;
+    }
+
+
+
     /**
      * This class represents the result obtained from the query. It will contain the document which
      * which matched the specified query string and specifications.
@@ -46,44 +70,59 @@
     public static final class Result {
         private final SearchResultProto.ResultProto mResultProto;
 
+        @Nullable
+        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
          */
-        // TODO(sidchhabra): Switch to Document constructor that takes proto.
         @NonNull
-        public AppSearch.Document getDocument() {
-            return AppSearch.Document.newBuilder(mResultProto.getDocument().getUri(),
-                    mResultProto.getDocument().getSchema())
-                    .setCreationTimestampMillis(mResultProto.getDocument().getCreationTimestampMs())
-                    .setScore(mResultProto.getDocument().getScore())
-                    .build();
+        public AppSearchDocument getDocument() {
+            if (mDocument == null) {
+                mDocument = new AppSearchDocument(mResultProto.getDocument());
+            }
+            return mDocument;
         }
 
-        // TODO(sidchhabra): Add Getter for ResultReader for Snippet.
+        /**
+         * Contains a list of Snippets that matched the request. Only populated when requested in
+         * {@link SearchSpec.Builder#setMaxSnippetSize(int)}.
+         * @return  List of matches based on {@link SearchSpec}, if snippeting is disabled and this
+         * method is called it will return {@code null}. Users can also restrict snippet population
+         * using {@link SearchSpec.Builder#setNumToSnippet} and
+         * {@link SearchSpec.Builder#setNumMatchesPerProperty}, for all results after that value
+         * this method will return {@code null}.
+         * @hide
+         */
+        // TODO(sidchhabra): Replace Document with proper constructor.
+        @Nullable
+        public List<MatchInfo> getMatchInfo() {
+            if (!mResultProto.hasSnippet()) {
+                return null;
+            }
+            AppSearchDocument document = getDocument();
+            List<MatchInfo> matchList = new ArrayList<>();
+            for (Iterator entryProtoIterator = mResultProto.getSnippet()
+                    .getEntriesList().iterator(); entryProtoIterator.hasNext(); ) {
+                SnippetProto.EntryProto entry = (SnippetProto.EntryProto) entryProtoIterator.next();
+                for (Iterator snippetMatchProtoIterator = entry.getSnippetMatchesList().iterator();
+                        snippetMatchProtoIterator.hasNext(); ) {
+                    matchList.add(new MatchInfo(entry.getPropertyName(),
+                            (SnippetMatchProto) snippetMatchProtoIterator.next(), document));
+                }
+            }
+            return matchList;
+        }
     }
 
     @Override
     public String toString() {
         return mSearchResultProto.toString();
     }
-
-    /**
-     * Returns a {@link Result} iterator. Returns Empty Iterator if there are no matching results.
-     * @hide
-     */
-    @NonNull
-    public Iterator<Result> getResults() {
-        List<Result> results = new ArrayList<>();
-        // TODO(sidchhabra): Pass results using a RemoteStream.
-        for (SearchResultProto.ResultProto resultProto : mSearchResultProto.getResultsList()) {
-            results.add(new Result(resultProto));
-        }
-        return results.iterator();
-    }
 }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
index 5df7108..c276ae1 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -19,25 +19,32 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 
+import com.google.android.icing.proto.ResultSpecProto;
+import com.google.android.icing.proto.ScoringSpecProto;
 import com.google.android.icing.proto.SearchSpecProto;
 import com.google.android.icing.proto.TermMatchType;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+
 /**
  * This class represents the specification logic for AppSearch. It can be used to set the type of
  * search, like prefix or exact only or apply filters to search for a specific schema type only etc.
  * @hide
- *
  */
 // TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
 public final class SearchSpec {
 
     private final SearchSpecProto mSearchSpecProto;
+    private final ResultSpecProto mResultSpecProto;
+    private final ScoringSpecProto mScoringSpecProto;
 
-    private SearchSpec(SearchSpecProto searchSpecProto) {
+    private SearchSpec(@NonNull SearchSpecProto searchSpecProto,
+            @NonNull ResultSpecProto resultSpecProto, @NonNull ScoringSpecProto scoringSpecProto) {
         mSearchSpecProto = searchSpecProto;
+        mResultSpecProto = resultSpecProto;
+        mScoringSpecProto = scoringSpecProto;
     }
 
     /** Creates a new {@link SearchSpec.Builder}. */
@@ -48,10 +55,22 @@
 
     /** @hide */
     @NonNull
-    SearchSpecProto getProto() {
+    SearchSpecProto getSearchSpecProto() {
         return mSearchSpecProto;
     }
 
+    /** @hide */
+    @NonNull
+    ResultSpecProto getResultSpecProto() {
+        return mResultSpecProto;
+    }
+
+    /** @hide */
+    @NonNull
+    ScoringSpecProto getScoringSpecProto() {
+        return mScoringSpecProto;
+    }
+
     /** Term Match Type for the query. */
     // NOTE: The integer values of these constants must match the proto enum constants in
     // {@link com.google.android.icing.proto.SearchSpecProto.termMatchType}
@@ -62,54 +81,167 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface TermMatchTypeCode {}
 
+    /**
+     * Query terms will only match exact tokens in the index.
+     * <p>Ex. A query term "foo" will only match indexed token "foo", and not "foot" or "football".
+     */
     public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1;
+    /**
+     * Query terms will match indexed tokens when the query term is a prefix of the token.
+     * <p>Ex. A query term "foo" will match indexed tokens like "foo", "foot", and "football".
+     */
     public static final int TERM_MATCH_TYPE_PREFIX = 2;
 
+    /** Ranking Strategy for query result.*/
+    // NOTE: The integer values of these constants must match the proto enum constants in
+    // {@link ScoringSpecProto.RankingStrategy.Code }
+    @IntDef(prefix = {"RANKING_STRATEGY_"}, value = {
+            RANKING_STRATEGY_NONE,
+            RANKING_STRATEGY_DOCUMENT_SCORE,
+            RANKING_STRATEGY_CREATION_TIMESTAMP
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RankingStrategyCode {}
+
+    /** No Ranking, results are returned in arbitrary order.*/
+    public static final int RANKING_STRATEGY_NONE = 0;
+    /** Ranked by app-provided document scores. */
+    public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1;
+    /** Ranked by document creation timestamps. */
+    public static final int RANKING_STRATEGY_CREATION_TIMESTAMP = 2;
+
+    /** Order for query result.*/
+    // NOTE: The integer values of these constants must match the proto enum constants in
+    // {@link ScoringSpecProto.Order.Code }
+    @IntDef(prefix = {"ORDER_"}, value = {
+            ORDER_DESCENDING,
+            ORDER_ASCENDING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface OrderCode {}
+
+    /** Search results will be returned in a descending order. */
+    public static final int ORDER_DESCENDING = 0;
+    /** Search results will be returned in an ascending order. */
+    public static final int ORDER_ASCENDING = 1;
+
     /** Builder for {@link SearchSpec objects}. */
     public static final class Builder {
 
-        private final SearchSpecProto.Builder mBuilder = SearchSpecProto.newBuilder();
+        private final SearchSpecProto.Builder mSearchSpecBuilder = SearchSpecProto.newBuilder();
+        private final ResultSpecProto.Builder mResultSpecBuilder = ResultSpecProto.newBuilder();
+        private final ScoringSpecProto.Builder mScoringSpecBuilder = ScoringSpecProto.newBuilder();
+        private final ResultSpecProto.SnippetSpecProto.Builder mSnippetSpecBuilder =
+                ResultSpecProto.SnippetSpecProto.newBuilder();
 
-        private Builder(){}
+        private Builder() {
+        }
 
         /**
          * Indicates how the query terms should match {@link TermMatchTypeCode} in the index.
-         *
-         *   TermMatchType.Code=EXACT_ONLY
-         *   Query terms will only match exact tokens in the index.
-         *   Ex. A query term "foo" will only match indexed token "foo", and not "foot"
-         *   or "football"
-         *
-         *   TermMatchType.Code=PREFIX
-         *   Query terms will match indexed tokens when the query term is a prefix of
-         *   the token.
-         *   Ex. A query term "foo" will match indexed tokens like "foo", "foot", and
-         *   "football".
          */
         @NonNull
         public Builder setTermMatchType(@TermMatchTypeCode int termMatchTypeCode) {
             TermMatchType.Code termMatchTypeCodeProto =
                     TermMatchType.Code.forNumber(termMatchTypeCode);
             if (termMatchTypeCodeProto == null) {
-                throw new IllegalArgumentException("Invalid term match type: " + termMatchTypeCode);
+                throw new IllegalArgumentException("Invalid term match type: "
+                        + termMatchTypeCode);
             }
-            mBuilder.setTermMatchType(termMatchTypeCodeProto);
+            mSearchSpecBuilder.setTermMatchType(termMatchTypeCodeProto);
             return this;
         }
 
         /**
-         * Adds a Schema type filter to {@link SearchSpec} Entry.
-         * Only search for documents that have the specified schema types.
-         * If unset, the query will search over all schema types.
+         * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that
+         * have the specified schema types.
+         * <p>If unset, the query will search over all schema types.
          */
         @NonNull
         public Builder setSchemaTypes(@NonNull String... schemaTypes) {
             for (String schemaType : schemaTypes) {
-                mBuilder.addSchemaTypeFilters(schemaType);
+                mSearchSpecBuilder.addSchemaTypeFilters(schemaType);
             }
             return this;
         }
 
+        /** Sets the maximum number of results to retrieve from the query */
+        @NonNull
+        public SearchSpec.Builder setNumToRetrieve(int numToRetrieve) {
+            mResultSpecBuilder.setNumToRetrieve(numToRetrieve);
+            return this;
+        }
+
+        /** Sets ranking strategy for AppSearch results.*/
+        @NonNull
+        public Builder setRankingStrategy(@RankingStrategyCode int rankingStrategy) {
+            ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto =
+                    ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategy);
+            if (rankingStrategyCodeProto == null) {
+                throw new IllegalArgumentException("Invalid result ranking strategy: "
+                        + rankingStrategyCodeProto);
+            }
+            mScoringSpecBuilder.setRankBy(rankingStrategyCodeProto);
+            return this;
+        }
+
+        /**
+         * Indicates the order of returned search results, the default is DESC, meaning that results
+         * with higher scores come first.
+         * <p>This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}.
+         */
+        @NonNull
+        public Builder setOrder(@OrderCode int order) {
+            ScoringSpecProto.Order.Code orderCodeProto =
+                    ScoringSpecProto.Order.Code.forNumber(order);
+            if (orderCodeProto == null) {
+                throw new IllegalArgumentException("Invalid result ranking order: "
+                        + orderCodeProto);
+            }
+            mScoringSpecBuilder.setOrderBy(orderCodeProto);
+            return this;
+        }
+
+        /**
+         * Only the first {@code numToSnippet} documents based on the ranking strategy
+         * will have snippet information provided.
+         * <p>If set to 0 (default), snippeting is disabled and
+         * {@link SearchResults.Result#getMatchInfo} will return {@code null} for that result.
+         */
+        @NonNull
+        public SearchSpec.Builder setNumToSnippet(int numToSnippet) {
+            mSnippetSpecBuilder.setNumToSnippet(numToSnippet);
+            return this;
+        }
+
+        /**
+         * Only the first {@code numMatchesPerProperty} matches for a every property of
+         * {@link AppSearchDocument} will contain snippet information.
+         * <p>If set to 0, snippeting is disabled and {@link SearchResults.Result#getMatchInfo}
+         * will return {@code null} for that result.
+         */
+        @NonNull
+        public SearchSpec.Builder setNumMatchesPerProperty(int numMatchesPerProperty) {
+            mSnippetSpecBuilder.setNumMatchesPerProperty(numMatchesPerProperty);
+            return this;
+        }
+
+        /**
+         * Sets {@code maxSnippetSize}, the maximum snippet size. Snippet windows start at
+         * {@code maxSnippetSize/2} bytes before the middle of the matching token and end at
+         * {@code maxSnippetSize/2} bytes after the middle of the matching token. It respects
+         * token boundaries, therefore the returned window may be smaller than requested.
+         * <p> Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will
+         * be returned. If matches enabled is also set to false, then snippeting is disabled.
+         * <p>Ex. {@code maxSnippetSize} = 16. "foo bar baz bat rat" with a query of "baz" will
+         * return a window of "bar baz bat" which is only 11 bytes long.
+         */
+        @NonNull
+        public SearchSpec.Builder setMaxSnippetSize(int maxSnippetSize) {
+            mSnippetSpecBuilder.setMaxWindowBytes(maxSnippetSize);
+            return this;
+        }
+
         /**
          * Constructs a new {@link SearchSpec} from the contents of this builder.
          *
@@ -117,11 +249,12 @@
          */
         @NonNull
         public SearchSpec build() {
-            if (mBuilder.getTermMatchType() == TermMatchType.Code.UNKNOWN) {
+            if (mSearchSpecBuilder.getTermMatchType() == TermMatchType.Code.UNKNOWN) {
                 throw new IllegalSearchSpecException("Missing termMatchType field.");
             }
-            return new SearchSpec(mBuilder.build());
+            mResultSpecBuilder.setSnippetSpec(mSnippetSpecBuilder);
+            return new SearchSpec(mSearchSpecBuilder.build(), mResultSpecBuilder.build(),
+                    mScoringSpecBuilder.build());
         }
     }
-
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index d2d9cf9..2608e84 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -35,6 +35,7 @@
 import com.google.android.icing.proto.SearchSpecProto;
 import com.google.android.icing.protobuf.InvalidProtocolBufferException;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -103,13 +104,38 @@
                 Binder.restoreCallingIdentity(callingIdentity);
             }
         }
+
+        @Override
+        public void getDocuments(String[] uris, AndroidFuture callback) {
+            Preconditions.checkNotNull(uris);
+            Preconditions.checkNotNull(callback);
+            int callingUid = Binder.getCallingUidOrThrow();
+            int callingUserId = UserHandle.getUserId(callingUid);
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
+                // Contains serialized DocumentProto. byte[][] is not transmissible via Binder.
+                List<byte[]> results = new ArrayList<>(uris.length);
+                for (String uri : uris) {
+                    DocumentProto result = impl.getDocument(callingUid, uri);
+                    results.add(result.toByteArray());
+                }
+                callback.complete(results);
+            } catch (Throwable t) {
+                callback.completeExceptionally(t);
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
         // TODO(sidchhabra):Init FakeIcing properly.
         // TODO(sidchhabra): Do this in a threadpool.
         @Override
-        public void query(@NonNull String queryExpression, @NonNull byte[] searchSpec,
-                AndroidFuture callback) {
-            Preconditions.checkNotNull(queryExpression);
+        public void query(@NonNull byte[] searchSpec, @NonNull byte[] resultSpec,
+                @NonNull byte[] scoringSpec, AndroidFuture callback) {
             Preconditions.checkNotNull(searchSpec);
+            Preconditions.checkNotNull(resultSpec);
+            Preconditions.checkNotNull(scoringSpec);
             SearchSpecProto searchSpecProto = null;
             try {
                 searchSpecProto = SearchSpecProto.parseFrom(searchSpec);
@@ -117,7 +143,7 @@
                 throw new RuntimeException(e);
             }
             SearchResultProto searchResults =
-                    mFakeIcing.query(queryExpression);
+                    mFakeIcing.query(searchSpecProto.getQuery());
             callback.complete(searchResults.toByteArray());
         }
     }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
index 04b4b14..7442d06 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
@@ -17,6 +17,7 @@
 package com.android.server.appsearch.impl;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Context;
 
@@ -106,30 +107,65 @@
         // Rewrite the type names to include the app's prefix
         String typePrefix = getTypePrefix(callingUid);
         DocumentProto.Builder documentBuilder = origDocument.toBuilder();
-        rewriteDocumentTypes(typePrefix, documentBuilder);
+        rewriteDocumentTypes(typePrefix, documentBuilder, /*add=*/ true);
         mFakeIcing.put(documentBuilder.build());
     }
 
     /**
-     * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend
+     * Retrieves a document from the AppSearch index by URI.
+     *
+     * @param callingUid The uid of the app calling AppSearch.
+     * @param uri The URI of the document to get.
+     * @return The Document contents, or {@code null} if no such URI exists in the system.
+     */
+    @Nullable
+    public DocumentProto getDocument(int callingUid, @NonNull String uri) {
+        String typePrefix = getTypePrefix(callingUid);
+        DocumentProto document = mFakeIcing.get(uri);
+        // Rewrite the type names to remove the app's prefix
+        DocumentProto.Builder documentBuilder = document.toBuilder();
+        rewriteDocumentTypes(typePrefix, documentBuilder, /*add=*/ false);
+        return documentBuilder.build();
+    }
+
+    /**
+     * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend or remove
      * {@code typePrefix}.
      *
-     * @param typePrefix The prefix to add
+     * @param typePrefix The prefix to add or remove
      * @param documentBuilder The document to mutate
+     * @param add Whether to add typePrefix to the types. If {@code false}, typePrefix will be
+     *     removed from the types.
+     * @throws IllegalArgumentException If {@code add=false} and the document has a type that
+     *     doesn't start with {@code typePrefix}.
      */
     @VisibleForTesting
     void rewriteDocumentTypes(
             @NonNull String typePrefix,
-            @NonNull DocumentProto.Builder documentBuilder) {
-        // Rewrite the type name to include the app's prefix
-        String newSchema = typePrefix + documentBuilder.getSchema();
+            @NonNull DocumentProto.Builder documentBuilder,
+            boolean add) {
+        // Rewrite the type name to include/remove the app's prefix
+        String newSchema;
+        if (add) {
+            newSchema = typePrefix + documentBuilder.getSchema();
+        } else {
+            newSchema = removePrefix(typePrefix, documentBuilder.getSchema());
+        }
         documentBuilder.setSchema(newSchema);
 
-        // Add namespace. If we ever allow users to set their own namespaces, this will have
+        // Add/remove namespace. If we ever allow users to set their own namespaces, this will have
         // to change to prepend the prefix instead of setting the whole namespace. We will also have
         // to store the namespaces in a map similar to the type map so we can rewrite queries with
         // empty namespaces.
-        documentBuilder.setNamespace(typePrefix);
+        if (add) {
+            documentBuilder.setNamespace(typePrefix);
+        } else if (!documentBuilder.getNamespace().equals(typePrefix)) {
+            throw new IllegalStateException(
+                    "Unexpected namespace \"" + documentBuilder.getNamespace()
+                            + "\" (expected \"" + typePrefix + "\")");
+        } else {
+            documentBuilder.clearNamespace();
+        }
 
         // Recurse into derived documents
         for (int propertyIdx = 0;
@@ -142,7 +178,7 @@
                 for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
                     DocumentProto.Builder derivedDocumentBuilder =
                             propertyBuilder.getDocumentValues(documentIdx).toBuilder();
-                    rewriteDocumentTypes(typePrefix, derivedDocumentBuilder);
+                    rewriteDocumentTypes(typePrefix, derivedDocumentBuilder, add);
                     propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
                 }
                 documentBuilder.setProperties(propertyIdx, propertyBuilder);
@@ -165,4 +201,13 @@
         }
         return callingUidName + "@" + mUserId + "/";
     }
+
+    @NonNull
+    private static String removePrefix(@NonNull String prefix, @NonNull String input) {
+        if (!input.startsWith(prefix)) {
+            throw new IllegalArgumentException(
+                    "Input \"" + input + "\" does not start with \"" + prefix + "\"");
+        }
+        return input.substring(prefix.length());
+    }
 }
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/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 51b911a..1dbad45 100644
--- a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ApexContext;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -48,6 +49,8 @@
 
     private static final String LOG_TAG = RuntimePermissionsPersistenceImpl.class.getSimpleName();
 
+    private static final String APEX_MODULE_NAME = "com.android.permission";
+
     private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml";
 
     private static final String TAG_PACKAGE = "package";
@@ -253,9 +256,8 @@
 
     @NonNull
     private static File getFile(@NonNull UserHandle user) {
-        // TODO: Use an API for this.
-        File dataDirectory = new File("/data/misc_de/" + user.getIdentifier()
-                + "/apexdata/com.android.permission");
+        ApexContext apexContext = ApexContext.getApexContext(APEX_MODULE_NAME);
+        File dataDirectory = apexContext.getDeviceProtectedDataDirForUser(user);
         return new File(dataDirectory, RUNTIME_PERMISSIONS_FILE_NAME);
     }
 }
diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index 5061742..06fad77 100644
--- a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ApexContext;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -50,6 +51,8 @@
 
     private static final String LOG_TAG = RolesPersistenceImpl.class.getSimpleName();
 
+    private static final String APEX_MODULE_NAME = "com.android.permission";
+
     private static final String ROLES_FILE_NAME = "roles.xml";
 
     private static final String TAG_ROLES = "roles";
@@ -209,9 +212,8 @@
 
     @NonNull
     private static File getFile(@NonNull UserHandle user) {
-        // TODO: Use an API for this.
-        File dataDirectory = new File("/data/misc_de/" + user.getIdentifier()
-                + "/apexdata/com.android.permission");
+        ApexContext apexContext = ApexContext.getApexContext(APEX_MODULE_NAME);
+        File dataDirectory = apexContext.getDeviceProtectedDataDirForUser(user);
         return new File(dataDirectory, ROLES_FILE_NAME);
     }
 }
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 98%
rename from core/java/android/app/StatsManager.java
rename to apex/statsd/framework/java/android/app/StatsManager.java
index 0ea05d8..ad1ac95 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;
@@ -702,7 +702,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/api/current.txt b/api/current.txt
index 3d4aa5b..2e99edd 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
@@ -3897,6 +3901,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 +6832,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);
@@ -6853,6 +6859,7 @@
     method @Nullable public java.util.List<java.lang.String> getPermittedAccessibilityServices(@NonNull android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
     method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName);
+    method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName);
     method @NonNull public java.util.List<java.lang.String> getProtectedPackages(@NonNull android.content.ComponentName);
     method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
     method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
@@ -6912,6 +6919,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);
@@ -6955,6 +6963,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);
@@ -6979,6 +6988,7 @@
     method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
     method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
+    method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean);
     method public void setProfileEnabled(@NonNull android.content.ComponentName);
     method public void setProfileName(@NonNull android.content.ComponentName, String);
     method public void setProtectedPackages(@NonNull android.content.ComponentName, @NonNull java.util.List<java.lang.String>);
@@ -7014,6 +7024,7 @@
     field public static final String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE";
     field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
     field public static final String ACTION_BIND_SECONDARY_LOCKSCREEN_SERVICE = "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
+    field public static final String ACTION_CHECK_POLICY_COMPLIANCE = "android.app.action.CHECK_POLICY_COMPLIANCE";
     field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
     field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
     field public static final String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE";
@@ -7137,6 +7148,9 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     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
@@ -7538,6 +7552,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;
   }
 
@@ -9965,6 +9980,7 @@
     method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display);
     method @NonNull public android.content.Context createFeatureContext(@Nullable String);
     method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public android.content.Context createWindowContext(int);
     method public abstract String[] databaseList();
     method public abstract boolean deleteDatabase(String);
     method public abstract boolean deleteFile(String);
@@ -9989,6 +10005,7 @@
     method public abstract java.io.File getDataDir();
     method public abstract java.io.File getDatabasePath(String);
     method public abstract java.io.File getDir(String, int);
+    method @Nullable public android.view.Display getDisplay();
     method @Nullable public final android.graphics.drawable.Drawable getDrawable(@DrawableRes int);
     method @Nullable public abstract java.io.File getExternalCacheDir();
     method public abstract java.io.File[] getExternalCacheDirs();
@@ -10101,6 +10118,7 @@
     field public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
     field public static final String CLIPBOARD_SERVICE = "clipboard";
     field public static final String COMPANION_DEVICE_SERVICE = "companiondevice";
+    field public static final String CONNECTIVITY_DIAGNOSTICS_SERVICE = "connectivity_diagnostics";
     field public static final String CONNECTIVITY_SERVICE = "connectivity";
     field public static final String CONSUMER_IR_SERVICE = "consumer_ir";
     field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@@ -10161,6 +10179,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";
@@ -11770,6 +11789,7 @@
     method @Nullable public CharSequence getAppLabel();
     method @Nullable public String getAppPackageName();
     method @NonNull public int[] getChildSessionIds();
+    method public long getCreatedMillis();
     method public int getInstallLocation();
     method public int getInstallReason();
     method @Nullable public String getInstallerPackageName();
@@ -13516,227 +13536,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();
   }
 
 }
@@ -16719,6 +16739,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";
@@ -16748,6 +16769,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
@@ -17144,6 +17166,7 @@
     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_STREAM_COMBINATIONS;
     field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.StreamConfigurationMap> SCALER_STREAM_CONFIGURATION_MAP;
@@ -17250,6 +17273,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 {
@@ -17422,6 +17447,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
@@ -17557,6 +17587,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;
@@ -17653,6 +17684,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;
@@ -23381,6 +23413,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();
@@ -23391,6 +23426,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;
@@ -23415,6 +23453,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();
@@ -23426,6 +23468,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
@@ -23829,6 +23875,8 @@
     method @NonNull public int[] getChannelCounts();
     method @NonNull public int[] getChannelIndexMasks();
     method @NonNull public int[] getChannelMasks();
+    method @NonNull public int[] getEncapsulationMetadataTypes();
+    method @NonNull public int[] getEncapsulationModes();
     method @NonNull public int[] getEncodings();
     method public int getId();
     method public CharSequence getProductName();
@@ -24186,8 +24234,10 @@
   public final class AudioPlaybackCaptureConfiguration {
     method @NonNull public int[] getExcludeUids();
     method @NonNull public int[] getExcludeUsages();
+    method @NonNull public int[] getExcludeUserIds();
     method @NonNull public int[] getMatchingUids();
     method @NonNull public int[] getMatchingUsages();
+    method @NonNull public int[] getMatchingUserIds();
     method @NonNull public android.media.projection.MediaProjection getMediaProjection();
   }
 
@@ -24195,9 +24245,11 @@
     ctor public AudioPlaybackCaptureConfiguration.Builder(@NonNull android.media.projection.MediaProjection);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(int);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUserId(int);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration build();
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUid(int);
     method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUsage(int);
+    method @NonNull public android.media.AudioPlaybackCaptureConfiguration.Builder excludeUserId(int);
   }
 
   public final class AudioPlaybackConfiguration implements android.os.Parcelable {
@@ -24449,6 +24501,8 @@
     field public static final int DUAL_MONO_MODE_LR = 1; // 0x1
     field public static final int DUAL_MONO_MODE_OFF = 0; // 0x0
     field public static final int DUAL_MONO_MODE_RR = 3; // 0x3
+    field public static final int ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR = 2; // 0x2
+    field public static final int ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER = 1; // 0x1
     field public static final int ENCAPSULATION_MODE_ELEMENTARY_STREAM = 1; // 0x1
     field public static final int ENCAPSULATION_MODE_HANDLE = 2; // 0x2
     field public static final int ENCAPSULATION_MODE_NONE = 0; // 0x0
@@ -25936,6 +25990,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";
@@ -27617,6 +27672,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;
@@ -29548,8 +29605,6 @@
   public class ConnectivityDiagnosticsManager {
     method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
     method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
-    field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
-    field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
   }
 
   public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
@@ -29559,21 +29614,44 @@
     method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
   }
 
-  public static class ConnectivityDiagnosticsManager.ConnectivityReport {
+  public static final class ConnectivityDiagnosticsManager.ConnectivityReport implements android.os.Parcelable {
     ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
-    field @NonNull public final android.os.PersistableBundle additionalInfo;
-    field @NonNull public final android.net.LinkProperties linkProperties;
-    field @NonNull public final android.net.Network network;
-    field @NonNull public final android.net.NetworkCapabilities networkCapabilities;
-    field public final long reportTimestamp;
+    method public int describeContents();
+    method @NonNull public android.os.PersistableBundle getAdditionalInfo();
+    method @NonNull public android.net.LinkProperties getLinkProperties();
+    method @NonNull public android.net.Network getNetwork();
+    method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+    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 class ConnectivityDiagnosticsManager.DataStallReport {
+  public static final class ConnectivityDiagnosticsManager.DataStallReport implements android.os.Parcelable {
     ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.os.PersistableBundle);
-    field public final int detectionMethod;
-    field @NonNull public final android.net.Network network;
-    field public final long reportTimestamp;
-    field @NonNull public final android.os.PersistableBundle stallDetails;
+    method public int describeContents();
+    method public int getDetectionMethod();
+    method @NonNull public android.net.Network getNetwork();
+    method public long getReportTimestamp();
+    method @NonNull public android.os.PersistableBundle getStallDetails();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    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 {
@@ -29716,6 +29794,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);
@@ -29944,6 +30051,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);
@@ -29953,6 +30061,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;
@@ -30064,6 +30173,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();
@@ -30344,6 +30461,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();
@@ -31071,7 +31195,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);
@@ -31084,7 +31208,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();
@@ -42726,6 +42850,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);
@@ -42755,10 +42880,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;
   }
@@ -43006,6 +43132,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 {
@@ -43525,7 +43952,7 @@
     field public static final int STATE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
     field public static final int STATE_KEYPHRASE_ENROLLED = 2; // 0x2
     field public static final int STATE_KEYPHRASE_UNENROLLED = 1; // 0x1
-    field public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
+    field @Deprecated public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; // 0xffffffff
   }
 
   public abstract static class AlwaysOnHotwordDetector.Callback {
@@ -45305,6 +45732,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
@@ -45633,6 +46063,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";
@@ -46127,6 +46558,7 @@
     field public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool";
     field public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING = "show_carrier_data_icon_pattern_string";
     field public static final String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
+    field public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL = "show_forwarded_number_bool";
     field public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
     field public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL = "show_ims_registration_status_bool";
     field public static final String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
@@ -46173,6 +46605,15 @@
     field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
 
+  public static final class CarrierConfigManager.Apn {
+    field public static final String KEY_PREFIX = "apn.";
+    field public static final String KEY_SETTINGS_DEFAULT_PROTOCOL_STRING = "apn.settings_default_protocol_string";
+    field public static final String KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING = "apn.settings_default_roaming_protocol_string";
+    field public static final String PROTOCOL_IPV4 = "IP";
+    field public static final String PROTOCOL_IPV4V6 = "IPV4V6";
+    field public static final String PROTOCOL_IPV6 = "IPV6";
+  }
+
   public static final class CarrierConfigManager.Gps {
     field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool";
     field public static final String KEY_PREFIX = "gps.";
@@ -46272,6 +46713,7 @@
 
   public final class CellIdentityLte extends android.telephony.CellIdentity {
     method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns();
+    method @NonNull public java.util.List<java.lang.Integer> getBands();
     method public int getBandwidth();
     method public int getCi();
     method @Nullable public android.telephony.ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo();
@@ -46289,7 +46731,7 @@
 
   public final class CellIdentityNr extends android.telephony.CellIdentity {
     method @NonNull public java.util.List<java.lang.String> getAdditionalPlmns();
-    method public int getBand();
+    method @NonNull public java.util.List<java.lang.Integer> getBands();
     method @Nullable public String getMccString();
     method @Nullable public String getMncString();
     method public long getNci();
@@ -47675,10 +48117,42 @@
     field public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2; // 0x2
     field public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; // 0x0
     field public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; // 0x1
+    field public static final int ERROR_ADDRESS_MISSING = 10011; // 0x271b
+    field public static final int ERROR_CARRIER_LOCKED = 10000; // 0x2710
+    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_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
+    field public static final int ERROR_NO_PROFILES_AVAILABLE = 10013; // 0x271d
+    field public static final int ERROR_OPERATION_BUSY = 10016; // 0x2720
+    field public static final int ERROR_SIM_MISSING = 10008; // 0x2718
+    field public static final int ERROR_TIME_OUT = 10005; // 0x2715
+    field public static final int ERROR_UNSUPPORTED_VERSION = 10007; // 0x2717
     field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
     field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
+    field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_ERROR_CODE";
+    field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_OPERATION_CODE";
+    field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE";
+    field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE";
     field public static final String EXTRA_USE_QR_SCANNER = "android.telephony.euicc.extra.USE_QR_SCANNER";
     field public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
+    field public static final int OPERATION_APDU = 8; // 0x8
+    field public static final int OPERATION_DOWNLOAD = 5; // 0x5
+    field public static final int OPERATION_EUICC_CARD = 3; // 0x3
+    field public static final int OPERATION_EUICC_GSMA = 7; // 0x7
+    field public static final int OPERATION_HTTP = 11; // 0xb
+    field public static final int OPERATION_METADATA = 6; // 0x6
+    field public static final int OPERATION_SIM_SLOT = 2; // 0x2
+    field public static final int OPERATION_SMDX = 9; // 0x9
+    field public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10; // 0xa
+    field public static final int OPERATION_SWITCH = 4; // 0x4
+    field public static final int OPERATION_SYSTEM = 1; // 0x1
   }
 
 }
@@ -52551,6 +53025,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);
@@ -52594,6 +53069,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);
@@ -52601,6 +53077,20 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.view.SurfaceControl.Transaction> CREATOR;
   }
 
+  public class SurfaceControlViewHost {
+    ctor public SurfaceControlViewHost(@NonNull android.content.Context, @NonNull android.view.Display, @Nullable android.os.IBinder);
+    method public void addView(@NonNull android.view.View, int, int);
+    method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage getSurfacePackage();
+    method public void relayout(int, int);
+    method public void release();
+  }
+
+  public static final class SurfaceControlViewHost.SurfacePackage implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.SurfaceControlViewHost.SurfacePackage> CREATOR;
+  }
+
   public interface SurfaceHolder {
     method public void addCallback(android.view.SurfaceHolder.Callback);
     method public android.view.Surface getSurface();
@@ -52645,7 +53135,9 @@
     ctor public SurfaceView(android.content.Context, android.util.AttributeSet, int, int);
     method public boolean gatherTransparentRegion(android.graphics.Region);
     method public android.view.SurfaceHolder getHolder();
+    method @Nullable public android.os.IBinder getHostToken();
     method public android.view.SurfaceControl getSurfaceControl();
+    method public void setChildSurfacePackage(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
     method public void setSecure(boolean);
     method public void setZOrderMediaOverlay(boolean);
     method public void setZOrderOnTop(boolean);
@@ -52785,7 +53277,7 @@
     method protected void dispatchSetPressed(boolean);
     method protected void dispatchSetSelected(boolean);
     method @CallSuper public void dispatchStartTemporaryDetach();
-    method public void dispatchSystemUiVisibilityChanged(int);
+    method @Deprecated public void dispatchSystemUiVisibilityChanged(int);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
     method public boolean dispatchUnhandledMove(android.view.View, int);
@@ -52795,7 +53287,7 @@
     method public void dispatchWindowInsetsAnimationPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
     method @NonNull public android.view.WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull android.view.WindowInsets);
     method @NonNull public android.view.WindowInsetsAnimationCallback.AnimationBounds dispatchWindowInsetsAnimationStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds);
-    method public void dispatchWindowSystemUiVisiblityChanged(int);
+    method @Deprecated public void dispatchWindowSystemUiVisiblityChanged(int);
     method public void dispatchWindowVisibilityChanged(int);
     method @CallSuper public void draw(android.graphics.Canvas);
     method @CallSuper public void drawableHotspotChanged(float, float);
@@ -52948,7 +53440,7 @@
     method protected int getSuggestedMinimumHeight();
     method protected int getSuggestedMinimumWidth();
     method @NonNull public java.util.List<android.graphics.Rect> getSystemGestureExclusionRects();
-    method public int getSystemUiVisibility();
+    method @Deprecated public int getSystemUiVisibility();
     method @android.view.ViewDebug.ExportedProperty public Object getTag();
     method public Object getTag(int);
     method @android.view.ViewDebug.ExportedProperty(category="text", mapping={@android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_INHERIT, to="INHERIT"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_GRAVITY, to="GRAVITY"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_TEXT_START, to="TEXT_START"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_TEXT_END, to="TEXT_END"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_CENTER, to="CENTER"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_VIEW_START, to="VIEW_START"), @android.view.ViewDebug.IntToString(from=android.view.View.TEXT_ALIGNMENT_VIEW_END, to="VIEW_END")}) public int getTextAlignment();
@@ -52976,7 +53468,7 @@
     method protected int getWindowAttachCount();
     method public android.view.WindowId getWindowId();
     method @Nullable public android.view.WindowInsetsController getWindowInsetsController();
-    method public int getWindowSystemUiVisibility();
+    method @Deprecated public int getWindowSystemUiVisibility();
     method public android.os.IBinder getWindowToken();
     method public int getWindowVisibility();
     method public void getWindowVisibleDisplayFrame(android.graphics.Rect);
@@ -53114,7 +53606,7 @@
     method @CallSuper public void onVisibilityAggregated(boolean);
     method protected void onVisibilityChanged(@NonNull android.view.View, int);
     method public void onWindowFocusChanged(boolean);
-    method public void onWindowSystemUiVisibilityChanged(int);
+    method @Deprecated public void onWindowSystemUiVisibilityChanged(int);
     method protected void onWindowVisibilityChanged(int);
     method protected boolean overScrollBy(int, int, int, int, int, int, int, int, boolean);
     method public boolean performAccessibilityAction(int, android.os.Bundle);
@@ -53256,7 +53748,7 @@
     method public void setOnKeyListener(android.view.View.OnKeyListener);
     method public void setOnLongClickListener(@Nullable android.view.View.OnLongClickListener);
     method public void setOnScrollChangeListener(android.view.View.OnScrollChangeListener);
-    method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
+    method @Deprecated public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
     method public void setOutlineAmbientShadowColor(@ColorInt int);
     method public void setOutlineProvider(android.view.ViewOutlineProvider);
@@ -53293,7 +53785,7 @@
     method public void setStateDescription(@Nullable CharSequence);
     method public void setStateListAnimator(android.animation.StateListAnimator);
     method public void setSystemGestureExclusionRects(@NonNull java.util.List<android.graphics.Rect>);
-    method public void setSystemUiVisibility(int);
+    method @Deprecated public void setSystemUiVisibility(int);
     method public void setTag(Object);
     method public void setTag(int, Object);
     method public void setTextAlignment(int);
@@ -53471,18 +53963,18 @@
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
     field @Deprecated public static final int STATUS_BAR_HIDDEN = 1; // 0x1
     field @Deprecated public static final int STATUS_BAR_VISIBLE = 0; // 0x0
-    field public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4; // 0x4
-    field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
-    field public static final int SYSTEM_UI_FLAG_IMMERSIVE = 2048; // 0x800
-    field public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096; // 0x1000
-    field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
-    field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
-    field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
-    field public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
-    field public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
-    field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
-    field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
-    field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
+    field @Deprecated public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4; // 0x4
+    field @Deprecated public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2
+    field @Deprecated public static final int SYSTEM_UI_FLAG_IMMERSIVE = 2048; // 0x800
+    field @Deprecated public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096; // 0x1000
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 16; // 0x10
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 8192; // 0x2000
+    field @Deprecated public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
+    field @Deprecated public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
+    field @Deprecated public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
     field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
     field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
     field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
@@ -53606,8 +54098,8 @@
     method public void onScrollChange(android.view.View, int, int, int, int);
   }
 
-  public static interface View.OnSystemUiVisibilityChangeListener {
-    method public void onSystemUiVisibilityChange(int);
+  @Deprecated public static interface View.OnSystemUiVisibilityChangeListener {
+    method @Deprecated public void onSystemUiVisibilityChange(int);
   }
 
   public static interface View.OnTouchListener {
@@ -54244,6 +54736,7 @@
     method public final void removeOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener);
     method public boolean requestFeature(int);
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
+    method public void resetOnContentApplyWindowInsetsListener();
     method public abstract void restoreHierarchyState(android.os.Bundle);
     method public abstract android.os.Bundle saveHierarchyState();
     method public void setAllowEnterTransitionOverlap(boolean);
@@ -54282,6 +54775,7 @@
     method public abstract void setNavigationBarColor(@ColorInt int);
     method public void setNavigationBarContrastEnforced(boolean);
     method public void setNavigationBarDividerColor(@ColorInt int);
+    method public void setOnContentApplyWindowInsetsListener(@Nullable android.view.Window.OnContentApplyWindowInsetsListener);
     method public void setPreferMinimalPostProcessing(boolean);
     method public void setReenterTransition(android.transition.Transition);
     method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
@@ -54376,6 +54870,10 @@
     method @Nullable public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback, int);
   }
 
+  public static interface Window.OnContentApplyWindowInsetsListener {
+    method @NonNull public android.util.Pair<android.graphics.Insets,android.view.WindowInsets> onContentApplyWindowInsets(@NonNull android.view.WindowInsets);
+  }
+
   public static interface Window.OnFrameMetricsAvailableListener {
     method public void onFrameMetricsAvailable(android.view.Window, android.view.FrameMetrics, int);
   }
@@ -54420,23 +54918,23 @@
     method @Deprecated @NonNull public android.view.WindowInsets consumeSystemWindowInsets();
     method @Nullable public android.view.DisplayCutout getDisplayCutout();
     method @NonNull public android.graphics.Insets getInsets(int);
-    method @NonNull public android.graphics.Insets getMandatorySystemGestureInsets();
-    method @NonNull public android.graphics.Insets getMaxInsets(int) throws java.lang.IllegalArgumentException;
-    method public int getStableInsetBottom();
-    method public int getStableInsetLeft();
-    method public int getStableInsetRight();
-    method public int getStableInsetTop();
-    method @NonNull public android.graphics.Insets getStableInsets();
-    method @NonNull public android.graphics.Insets getSystemGestureInsets();
-    method public int getSystemWindowInsetBottom();
-    method public int getSystemWindowInsetLeft();
-    method public int getSystemWindowInsetRight();
-    method public int getSystemWindowInsetTop();
-    method @NonNull public android.graphics.Insets getSystemWindowInsets();
-    method @NonNull public android.graphics.Insets getTappableElementInsets();
+    method @NonNull public android.graphics.Insets getInsetsIgnoringVisibility(int);
+    method @Deprecated @NonNull public android.graphics.Insets getMandatorySystemGestureInsets();
+    method @Deprecated public int getStableInsetBottom();
+    method @Deprecated public int getStableInsetLeft();
+    method @Deprecated public int getStableInsetRight();
+    method @Deprecated public int getStableInsetTop();
+    method @Deprecated @NonNull public android.graphics.Insets getStableInsets();
+    method @Deprecated @NonNull public android.graphics.Insets getSystemGestureInsets();
+    method @Deprecated public int getSystemWindowInsetBottom();
+    method @Deprecated public int getSystemWindowInsetLeft();
+    method @Deprecated public int getSystemWindowInsetRight();
+    method @Deprecated public int getSystemWindowInsetTop();
+    method @Deprecated @NonNull public android.graphics.Insets getSystemWindowInsets();
+    method @Deprecated @NonNull public android.graphics.Insets getTappableElementInsets();
     method public boolean hasInsets();
-    method public boolean hasStableInsets();
-    method public boolean hasSystemWindowInsets();
+    method @Deprecated public boolean hasStableInsets();
+    method @Deprecated public boolean hasSystemWindowInsets();
     method @NonNull public android.view.WindowInsets inset(@IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int);
     method public boolean isConsumed();
     method public boolean isRound();
@@ -54452,17 +54950,24 @@
     method @NonNull public android.view.WindowInsets build();
     method @NonNull public android.view.WindowInsets.Builder setDisplayCutout(@Nullable android.view.DisplayCutout);
     method @NonNull public android.view.WindowInsets.Builder setInsets(int, @NonNull android.graphics.Insets);
-    method @NonNull public android.view.WindowInsets.Builder setMandatorySystemGestureInsets(@NonNull android.graphics.Insets);
-    method @NonNull public android.view.WindowInsets.Builder setMaxInsets(int, @NonNull android.graphics.Insets) throws java.lang.IllegalArgumentException;
-    method @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets);
-    method @NonNull public android.view.WindowInsets.Builder setSystemGestureInsets(@NonNull android.graphics.Insets);
-    method @NonNull public android.view.WindowInsets.Builder setSystemWindowInsets(@NonNull android.graphics.Insets);
-    method @NonNull public android.view.WindowInsets.Builder setTappableElementInsets(@NonNull android.graphics.Insets);
+    method @NonNull public android.view.WindowInsets.Builder setInsetsIgnoringVisibility(int, @NonNull android.graphics.Insets) throws java.lang.IllegalArgumentException;
+    method @Deprecated @NonNull public android.view.WindowInsets.Builder setMandatorySystemGestureInsets(@NonNull android.graphics.Insets);
+    method @Deprecated @NonNull public android.view.WindowInsets.Builder setStableInsets(@NonNull android.graphics.Insets);
+    method @Deprecated @NonNull public android.view.WindowInsets.Builder setSystemGestureInsets(@NonNull android.graphics.Insets);
+    method @Deprecated @NonNull public android.view.WindowInsets.Builder setSystemWindowInsets(@NonNull android.graphics.Insets);
+    method @Deprecated @NonNull public android.view.WindowInsets.Builder setTappableElementInsets(@NonNull android.graphics.Insets);
     method @NonNull public android.view.WindowInsets.Builder setVisible(int, boolean);
   }
 
-  public static final class WindowInsets.Type {
+  public static final class WindowInsets.Side {
     method public static int all();
+    field public static final int BOTTOM = 8; // 0x8
+    field public static final int LEFT = 1; // 0x1
+    field public static final int RIGHT = 4; // 0x4
+    field public static final int TOP = 2; // 0x2
+  }
+
+  public static final class WindowInsets.Type {
     method public static int captionBar();
     method public static int ime();
     method public static int mandatorySystemGestures();
@@ -54471,7 +54976,6 @@
     method public static int systemBars();
     method public static int systemGestures();
     method public static int tappableElement();
-    method public static int windowDecor();
   }
 
   public interface WindowInsetsAnimationCallback {
@@ -54499,7 +55003,7 @@
     method public float getInterpolatedFraction();
     method @Nullable public android.view.animation.Interpolator getInterpolator();
     method public int getTypeMask();
-    method public void setDuration(long);
+    method public void setAlpha(@FloatRange(from=0.0f, to=1.0f) float);
     method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
   }
 
@@ -54520,19 +55024,27 @@
   }
 
   public interface WindowInsetsController {
-    method public default void controlInputMethodAnimation(long, @NonNull android.view.WindowInsetsAnimationControlListener);
+    method public default void controlInputMethodAnimation(long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
+    method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
     method public int getSystemBarsAppearance();
     method public int getSystemBarsBehavior();
+    method public void hide(int);
     method public default void hideInputMethod();
     method public void setSystemBarsAppearance(int, int);
     method public void setSystemBarsBehavior(int);
+    method public void show(int);
     method public default void showInputMethod();
     field public static final int APPEARANCE_LIGHT_NAVIGATION_BARS = 16; // 0x10
     field public static final int APPEARANCE_LIGHT_STATUS_BARS = 8; // 0x8
+    field public static final int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1; // 0x1
+    field public static final int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0; // 0x0
+    field public static final int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2; // 0x2
   }
 
   public interface WindowManager extends android.view.ViewManager {
-    method public android.view.Display getDefaultDisplay();
+    method @NonNull public default android.view.WindowMetrics getCurrentWindowMetrics();
+    method @Deprecated public android.view.Display getDefaultDisplay();
+    method @NonNull public default android.view.WindowMetrics getMaximumWindowMetrics();
     method public void removeViewImmediate(android.view.View);
   }
 
@@ -54558,9 +55070,15 @@
     method public String debug(String);
     method public int describeContents();
     method public int getColorMode();
+    method public int getFitInsetsSides();
+    method public int getFitInsetsTypes();
     method public final CharSequence getTitle();
+    method public boolean isFitInsetsIgnoringVisibility();
     method public static boolean mayUseInputMethod(int);
     method public void setColorMode(int);
+    method public void setFitInsetsIgnoringVisibility(boolean);
+    method public void setFitInsetsSides(int);
+    method public void setFitInsetsTypes(int);
     method public final void setTitle(CharSequence);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ALPHA_CHANGED = 128; // 0x80
@@ -54581,13 +55099,13 @@
     field @Deprecated public static final int FLAG_DISMISS_KEYGUARD = 4194304; // 0x400000
     field @Deprecated public static final int FLAG_DITHER = 4096; // 0x1000
     field public static final int FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS = -2147483648; // 0x80000000
-    field public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
-    field public static final int FLAG_FULLSCREEN = 1024; // 0x400
+    field @Deprecated public static final int FLAG_FORCE_NOT_FULLSCREEN = 2048; // 0x800
+    field @Deprecated public static final int FLAG_FULLSCREEN = 1024; // 0x400
     field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000
     field public static final int FLAG_IGNORE_CHEEK_PRESSES = 32768; // 0x8000
     field public static final int FLAG_KEEP_SCREEN_ON = 128; // 0x80
-    field public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 1073741824; // 0x40000000
-    field public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000
+    field @Deprecated public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 1073741824; // 0x40000000
+    field @Deprecated public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000
     field @Deprecated public static final int FLAG_LAYOUT_IN_OVERSCAN = 33554432; // 0x2000000
     field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100
     field public static final int FLAG_LAYOUT_NO_LIMITS = 512; // 0x200
@@ -54601,8 +55119,8 @@
     field @Deprecated public static final int FLAG_SHOW_WHEN_LOCKED = 524288; // 0x80000
     field public static final int FLAG_SPLIT_TOUCH = 8388608; // 0x800000
     field @Deprecated public static final int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
-    field public static final int FLAG_TRANSLUCENT_NAVIGATION = 134217728; // 0x8000000
-    field public static final int FLAG_TRANSLUCENT_STATUS = 67108864; // 0x4000000
+    field @Deprecated public static final int FLAG_TRANSLUCENT_NAVIGATION = 134217728; // 0x8000000
+    field @Deprecated public static final int FLAG_TRANSLUCENT_STATUS = 67108864; // 0x4000000
     field @Deprecated public static final int FLAG_TURN_SCREEN_ON = 2097152; // 0x200000
     field public static final int FLAG_WATCH_OUTSIDE_TOUCH = 262144; // 0x40000
     field public static final int FORMAT_CHANGED = 8; // 0x8
@@ -54628,7 +55146,7 @@
     field public static final int SCREEN_ORIENTATION_CHANGED = 1024; // 0x400
     field public static final int SOFT_INPUT_ADJUST_NOTHING = 48; // 0x30
     field public static final int SOFT_INPUT_ADJUST_PAN = 32; // 0x20
-    field public static final int SOFT_INPUT_ADJUST_RESIZE = 16; // 0x10
+    field @Deprecated public static final int SOFT_INPUT_ADJUST_RESIZE = 16; // 0x10
     field public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0; // 0x0
     field public static final int SOFT_INPUT_IS_FORWARD_NAVIGATION = 256; // 0x100
     field public static final int SOFT_INPUT_MASK_ADJUST = 240; // 0xf0
@@ -54685,7 +55203,7 @@
     field public float screenBrightness;
     field public int screenOrientation;
     field public int softInputMode;
-    field public int systemUiVisibility;
+    field @Deprecated public int systemUiVisibility;
     field public android.os.IBinder token;
     field @android.view.ViewDebug.ExportedProperty(mapping={@android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION, to="BASE_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION, to="APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING, to="APPLICATION_STARTING"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION, to="DRAWN_APPLICATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, to="APPLICATION_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA, to="APPLICATION_MEDIA"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, to="APPLICATION_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x3ed, to="APPLICATION_ABOVE_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG, to="APPLICATION_ATTACHED_DIALOG"), @android.view.ViewDebug.IntToString(from=0x3ec, to="APPLICATION_MEDIA_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR, to="STATUS_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR, to="SEARCH_BAR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PHONE, to="PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, to="SYSTEM_ALERT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_TOAST, to="TOAST"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, to="SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE, to="PRIORITY_PHONE"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG, to="SYSTEM_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, to="KEYGUARD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, to="SYSTEM_ERROR"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD, to="INPUT_METHOD"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, to="INPUT_METHOD_DIALOG"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_WALLPAPER, to="WALLPAPER"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, to="STATUS_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7df, to="SECURE_SYSTEM_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e0, to="DRAG"), @android.view.ViewDebug.IntToString(from=0x7e1, to="STATUS_BAR_SUB_PANEL"), @android.view.ViewDebug.IntToString(from=0x7e2, to="POINTER"), @android.view.ViewDebug.IntToString(from=0x7e3, to="NAVIGATION_BAR"), @android.view.ViewDebug.IntToString(from=0x7e4, to="VOLUME_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7e5, to="BOOT_PROGRESS"), @android.view.ViewDebug.IntToString(from=0x7e6, to="INPUT_CONSUMER"), @android.view.ViewDebug.IntToString(from=0x7e7, to="DREAM"), @android.view.ViewDebug.IntToString(from=0x7e8, to="NAVIGATION_BAR_PANEL"), @android.view.ViewDebug.IntToString(from=0x7ea, to="DISPLAY_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7eb, to="MAGNIFICATION_OVERLAY"), @android.view.ViewDebug.IntToString(from=0x7f5, to="PRESENTATION"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION, to="PRIVATE_PRESENTATION"), @android.view.ViewDebug.IntToString(from=0x7ef, to="VOICE_INTERACTION"), @android.view.ViewDebug.IntToString(from=0x7f1, to="VOICE_INTERACTION_STARTING"), @android.view.ViewDebug.IntToString(from=0x7f2, to="DOCK_DIVIDER"), @android.view.ViewDebug.IntToString(from=0x7f3, to="QS_DIALOG"), @android.view.ViewDebug.IntToString(from=0x7f4, to="SCREENSHOT"), @android.view.ViewDebug.IntToString(from=android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, to="APPLICATION_OVERLAY")}) public int type;
     field public float verticalMargin;
@@ -54695,6 +55213,12 @@
     field @android.view.ViewDebug.ExportedProperty public int y;
   }
 
+  public final class WindowMetrics {
+    ctor public WindowMetrics(@NonNull android.util.Size, @NonNull android.view.WindowInsets);
+    method @NonNull public android.util.Size getSize();
+    method @NonNull public android.view.WindowInsets getWindowInsets();
+  }
+
 }
 
 package android.view.accessibility {
@@ -55628,6 +56152,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 {
@@ -55676,6 +56201,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 {
@@ -55792,7 +56335,12 @@
     ctor public EditorInfo();
     method public int describeContents();
     method public void dump(android.util.Printer, String);
+    method @Nullable public CharSequence getInitialSelectedText(int);
+    method @Nullable public CharSequence getInitialTextAfterCursor(int, int);
+    method @Nullable public CharSequence getInitialTextBeforeCursor(int, int);
     method public final void makeCompatible(int);
+    method public void setInitialSurroundingSubText(@NonNull CharSequence, int);
+    method public void setInitialSurroundingText(@NonNull CharSequence);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.EditorInfo> CREATOR;
     field public static final int IME_ACTION_DONE = 6; // 0x6
@@ -55872,10 +56420,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 da96583..6a88822 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";
@@ -59,10 +60,12 @@
     field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
     field public static final String CHANGE_DEVICE_IDLE_TEMP_WHITELIST = "android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST";
     field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
+    field public static final String COMPANION_APPROVE_WIFI_CONNECTIONS = "android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS";
     field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
     field public static final String CONFIGURE_WIFI_DISPLAY = "android.permission.CONFIGURE_WIFI_DISPLAY";
     field @Deprecated public static final String CONNECTIVITY_INTERNAL = "android.permission.CONNECTIVITY_INTERNAL";
     field public static final String CONNECTIVITY_USE_RESTRICTED_NETWORKS = "android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS";
+    field public static final String CONTROL_DEVICE_LIGHTS = "android.permission.CONTROL_DEVICE_LIGHTS";
     field public static final String CONTROL_DISPLAY_COLOR_TRANSFORMS = "android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS";
     field public static final String CONTROL_DISPLAY_SATURATION = "android.permission.CONTROL_DISPLAY_SATURATION";
     field public static final String CONTROL_INCALL_EXPERIENCE = "android.permission.CONTROL_INCALL_EXPERIENCE";
@@ -130,6 +133,7 @@
     field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
     field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE";
     field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE";
+    field public static final String MONITOR_DEVICE_CONFIG_ACCESS = "android.permission.MONITOR_DEVICE_CONFIG_ACCESS";
     field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
     field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
     field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
@@ -187,6 +191,7 @@
     field public static final String REMOTE_DISPLAY_PROVIDER = "android.permission.REMOTE_DISPLAY_PROVIDER";
     field public static final String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES";
     field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
+    field public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
     field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
     field public static final String RESTORE_RUNTIME_PERMISSIONS = "android.permission.RESTORE_RUNTIME_PERMISSIONS";
@@ -232,7 +237,7 @@
     field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
     field public static final String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE";
     field public static final String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS";
-    field public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
+    field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
     field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
   }
 
@@ -242,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
@@ -293,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 {
@@ -389,6 +400,7 @@
     field public static final String OPSTR_POST_NOTIFICATION = "android:post_notification";
     field public static final String OPSTR_PROJECT_MEDIA = "android:project_media";
     field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard";
+    field public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
     field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms";
     field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio";
     field public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images";
@@ -616,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 {
@@ -1714,7 +1729,7 @@
 package android.companion {
 
   public final class CompanionDeviceManager {
-    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
   }
 
 }
@@ -1819,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";
@@ -1834,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";
@@ -1886,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();
@@ -1915,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
@@ -2030,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;
   }
 
 }
@@ -2058,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[]);
@@ -2148,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 {
@@ -2227,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);
@@ -2237,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
@@ -2300,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 {
@@ -2365,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;
   }
 
@@ -2374,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);
   }
@@ -2923,12 +2894,54 @@
 
 }
 
+package android.hardware.lights {
+
+  public final class Light implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getId();
+    method public int getOrdinal();
+    method public int getType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
+  }
+
+  public final class LightState implements android.os.Parcelable {
+    ctor public LightState(@ColorInt int);
+    method public int describeContents();
+    method @ColorInt public int getColor();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
+  }
+
+  public final class LightsManager {
+    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public java.util.List<android.hardware.lights.Light> getLights();
+    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightsManager.LightsSession openSession();
+    field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
+  }
+
+  public final class LightsManager.LightsSession implements java.lang.AutoCloseable {
+    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void close();
+    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void setLights(@NonNull android.hardware.lights.LightsRequest);
+  }
+
+  public final class LightsRequest {
+  }
+
+  public static final class LightsRequest.Builder {
+    ctor public LightsRequest.Builder();
+    method @NonNull public android.hardware.lights.LightsRequest build();
+    method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
+    method @NonNull public android.hardware.lights.LightsRequest.Builder setLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
+  }
+
+}
+
 package android.hardware.location {
 
   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 {
@@ -2977,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
@@ -3635,9 +3648,34 @@
 package android.hardware.soundtrigger {
 
   public class SoundTrigger {
+    field public static final int RECOGNITION_MODE_GENERIC = 8; // 0x8
+    field public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 4; // 0x4
+    field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
+    field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
     field public static final int STATUS_OK = 0; // 0x0
   }
 
+  public static final class SoundTrigger.Keyphrase implements android.os.Parcelable {
+    ctor public SoundTrigger.Keyphrase(int, int, @NonNull java.util.Locale, @NonNull String, @Nullable int[]);
+    method @NonNull public static android.hardware.soundtrigger.SoundTrigger.Keyphrase readFromParcel(@NonNull android.os.Parcel);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.Keyphrase> CREATOR;
+    field public final int id;
+    field @NonNull public final java.util.Locale locale;
+    field public final int recognitionModes;
+    field @NonNull public final String text;
+    field @NonNull public final int[] users;
+  }
+
+  public static final class SoundTrigger.KeyphraseSoundModel extends android.hardware.soundtrigger.SoundTrigger.SoundModel implements android.os.Parcelable {
+    ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int);
+    ctor public SoundTrigger.KeyphraseSoundModel(@NonNull java.util.UUID, @NonNull java.util.UUID, @Nullable byte[], @Nullable android.hardware.soundtrigger.SoundTrigger.Keyphrase[]);
+    method @NonNull public static android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel readFromParcel(@NonNull android.os.Parcel);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel> CREATOR;
+    field @NonNull public final android.hardware.soundtrigger.SoundTrigger.Keyphrase[] keyphrases;
+  }
+
   public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModelParamRange> CREATOR;
@@ -3676,6 +3714,16 @@
     method public boolean isCaptureAvailable();
   }
 
+  public static class SoundTrigger.SoundModel {
+    field public static final int TYPE_GENERIC_SOUND = 1; // 0x1
+    field public static final int TYPE_KEYPHRASE = 0; // 0x0
+    field @NonNull public final byte[] data;
+    field public final int type;
+    field @NonNull public final java.util.UUID uuid;
+    field @NonNull public final java.util.UUID vendorUuid;
+    field public final int version;
+  }
+
 }
 
 package android.hardware.usb {
@@ -3692,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";
   }
 
@@ -3751,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;
   }
@@ -3765,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);
@@ -4185,9 +4240,11 @@
     method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes);
     method public void clearAudioServerStateCallback();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
+    method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAddress> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
+    method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAddress getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
@@ -4201,6 +4258,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException;
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.MODIFY_AUDIO_ROUTING}) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int, android.media.audiopolicy.AudioPolicy) throws java.lang.IllegalArgumentException;
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int requestAudioFocus(@NonNull android.media.AudioFocusRequest, @Nullable android.media.audiopolicy.AudioPolicy);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
     method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAddress);
@@ -4327,6 +4385,7 @@
     field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
     field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
     field public static final int RULE_MATCH_UID = 4; // 0x4
+    field public static final int RULE_MATCH_USERID = 8; // 0x8
   }
 
   public static class AudioMixingRule.Builder {
@@ -4347,9 +4406,11 @@
     method public int getFocusDuckingBehavior();
     method public int getStatus();
     method public boolean removeUidDeviceAffinity(int);
+    method public boolean removeUserIdDeviceAffinity(int);
     method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setRegistration(String);
     method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
+    method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
     method public String toLogFriendlyString();
     field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
     field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
@@ -4503,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;
   }
@@ -5013,6 +5074,7 @@
   }
 
   public class MediaEvent extends android.media.tv.tuner.filter.FilterEvent {
+    method public long getAudioHandle();
     method public long getAvDataId();
     method public long getDataLength();
     method @Nullable public android.media.tv.tuner.filter.AudioDescriptor getExtraMetaData();
@@ -5880,6 +5942,16 @@
 
 }
 
+package android.media.voice {
+
+  public final class KeyphraseModelManager {
+    method @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public void deleteKeyphraseSoundModel(int, @NonNull java.util.Locale);
+    method @Nullable @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel getKeyphraseSoundModel(int, @NonNull java.util.Locale);
+    method @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public void updateKeyphraseSoundModel(@NonNull android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel);
+  }
+
+}
+
 package android.metrics {
 
   public class LogMaker {
@@ -5974,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);
@@ -5991,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 {
@@ -6075,13 +6147,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 {
@@ -6198,9 +6275,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
@@ -6209,7 +6288,7 @@
 
   public class NetworkKey implements android.os.Parcelable {
     ctor public NetworkKey(android.net.WifiKey);
-    method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult);
+    method @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
@@ -6260,12 +6339,12 @@
   }
 
   public class NetworkScoreManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage();
-    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
-    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage();
+    method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
+    method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(@NonNull java.util.Collection<android.net.NetworkKey>) throws java.lang.SecurityException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
     method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
     field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
     field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
@@ -6280,9 +6359,10 @@
     field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
   }
 
-  public static interface NetworkScoreManager.NetworkScoreCallback {
-    method public void clearScores();
-    method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
+  public abstract static class NetworkScoreManager.NetworkScoreCallback {
+    ctor public NetworkScoreManager.NetworkScoreCallback();
+    method public abstract void onScoresInvalidated();
+    method public abstract void onScoresUpdated(@NonNull java.util.Collection<android.net.ScoredNetwork>);
   }
 
   public abstract class NetworkSpecifier {
@@ -6391,25 +6471,36 @@
     method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
   }
 
-  public final class StringNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
-    ctor public StringNetworkSpecifier(@NonNull String);
-    method public int describeContents();
-    method public boolean satisfiedBy(android.net.NetworkSpecifier);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.StringNetworkSpecifier> CREATOR;
-    field @NonNull public final String specifier;
-  }
-
   public final class TelephonyNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
     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";
@@ -6417,6 +6508,7 @@
     field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
     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
@@ -6442,8 +6534,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>);
@@ -6459,6 +6558,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();
@@ -6648,7 +6758,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);
@@ -6657,6 +6767,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();
@@ -6670,6 +6781,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);
@@ -6683,6 +6796,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 {
   }
 
@@ -6704,6 +6825,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;
@@ -6751,7 +6875,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 {
@@ -6768,33 +6892,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 {
@@ -7416,12 +7540,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
@@ -7459,6 +7583,7 @@
   public class WifiManager {
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoin(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoinGlobal(boolean);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoinPasspoint(@NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void clearWifiConnectedNetworkScorer();
     method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
@@ -7489,11 +7614,8 @@
     method public boolean isPortableHotspotSupported();
     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[]);
@@ -7504,6 +7626,7 @@
     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 @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);
@@ -7869,6 +7992,7 @@
   }
 
   public final class PasspointConfiguration implements android.os.Parcelable {
+    method public int getMeteredOverride();
     method public boolean isAutoJoinEnabled();
     method public boolean isMacRandomizationEnabled();
   }
@@ -8232,19 +8356,19 @@
   public 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
@@ -8654,6 +8778,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();
@@ -8688,16 +8832,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();
   }
 
@@ -8918,12 +9058,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();
@@ -9033,6 +9173,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>);
@@ -9465,6 +9606,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";
@@ -9628,6 +9770,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";
@@ -9685,6 +9828,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 {
@@ -10004,6 +10155,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>);
@@ -10012,6 +10164,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();
@@ -10040,6 +10202,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;
   }
 
 }
@@ -10108,6 +10280,7 @@
   public abstract class EuiccService extends android.app.Service {
     ctor public EuiccService();
     method public void dump(@NonNull java.io.PrintWriter);
+    method public int encodeSmdxSubjectAndReasonCode(@Nullable String, @Nullable String) throws java.lang.IllegalArgumentException, java.lang.NumberFormatException, java.lang.UnsupportedOperationException;
     method @CallSuper public android.os.IBinder onBind(android.content.Intent);
     method public abstract int onDeleteSubscription(int, String);
     method public android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, @NonNull android.telephony.euicc.DownloadableSubscription, boolean, boolean, @Nullable android.os.Bundle);
@@ -10468,6 +10641,14 @@
 
 }
 
+package android.service.voice {
+
+  public class VoiceInteractionService extends android.app.Service {
+    method @NonNull @RequiresPermission("android.permission.MANAGE_VOICE_KEYPHRASES") public final android.media.voice.KeyphraseModelManager createKeyphraseModelManager();
+  }
+
+}
+
 package android.service.wallpaper {
 
   public class WallpaperService.Engine {
@@ -10709,7 +10890,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 {
@@ -10795,10 +10983,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
@@ -11456,7 +11654,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();
@@ -12048,6 +12246,7 @@
     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>);
@@ -12195,6 +12394,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);
@@ -12211,6 +12411,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);
@@ -12219,6 +12422,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);
@@ -12524,6 +12728,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";
@@ -12689,6 +12898,7 @@
     field public static final String EXTRA_DIALSTRING = "dialstring";
     field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
     field public static final String EXTRA_EMERGENCY_CALL = "e_call";
+    field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
     field public static final String EXTRA_IS_CALL_PULL = "CallPull";
     field public static final String EXTRA_OI = "oi";
     field public static final String EXTRA_OIR = "oir";
@@ -13217,6 +13427,29 @@
     method @NonNull public android.telephony.ims.RcsContactUceCapability build();
   }
 
+  public class RcsUceAdapter {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isUceSettingEnabled() 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
+  }
+
 }
 
 package android.telephony.ims.feature {
@@ -13478,6 +13711,7 @@
     method public int transact(android.os.Bundle);
     method public int updateCallBarring(int, int, String[]);
     method public int updateCallBarringForServiceClass(int, int, String[], int);
+    method public int updateCallBarringWithPassword(int, int, @Nullable String[], int, @NonNull String);
     method public int updateCallForward(int, int, String, int, int);
     method public int updateCallWaiting(boolean, int);
     method public int updateClip(boolean);
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 1edc08c..e7a0cf6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10,6 +10,7 @@
     field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
     field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
     field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+    field public static final String CONTROL_DEVICE_LIGHTS = "android.permission.CONTROL_DEVICE_LIGHTS";
     field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
     field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES";
@@ -19,7 +20,7 @@
     field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
     field public static final String TEST_MANAGE_ROLLBACKS = "android.permission.TEST_MANAGE_ROLLBACKS";
     field public static final String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG";
-    field public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
+    field @Deprecated public static final String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE";
     field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
   }
 
@@ -76,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
@@ -704,7 +707,7 @@
 package android.companion {
 
   public final class CompanionDeviceManager {
-    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
   }
 
 }
@@ -758,7 +761,6 @@
     method @NonNull public android.content.Context createContextAsUser(@NonNull android.os.UserHandle, int);
     method @NonNull public android.content.Context createPackageContextAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public java.io.File getCrateDir(@NonNull String);
-    method public abstract android.view.Display getDisplay();
     method public abstract int getDisplayId();
     method public android.os.UserHandle getUser();
     method public int getUserId();
@@ -779,7 +781,6 @@
   }
 
   public class ContextWrapper extends android.content.Context {
-    method public android.view.Display getDisplay();
     method public int getDisplayId();
   }
 
@@ -1132,6 +1133,49 @@
 
 }
 
+package android.hardware.lights {
+
+  public final class Light implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getId();
+    method public int getOrdinal();
+    method public int getType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
+  }
+
+  public final class LightState implements android.os.Parcelable {
+    ctor public LightState(@ColorInt int);
+    method public int describeContents();
+    method @ColorInt public int getColor();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.LightState> CREATOR;
+  }
+
+  public final class LightsManager {
+    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightState getLightState(@NonNull android.hardware.lights.Light);
+    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public java.util.List<android.hardware.lights.Light> getLights();
+    method @NonNull @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public android.hardware.lights.LightsManager.LightsSession openSession();
+    field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
+  }
+
+  public final class LightsManager.LightsSession implements java.lang.AutoCloseable {
+    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void close();
+    method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_LIGHTS) public void setLights(@NonNull android.hardware.lights.LightsRequest);
+  }
+
+  public final class LightsRequest {
+  }
+
+  public static final class LightsRequest.Builder {
+    ctor public LightsRequest.Builder();
+    method @NonNull public android.hardware.lights.LightsRequest build();
+    method @NonNull public android.hardware.lights.LightsRequest.Builder clearLight(@NonNull android.hardware.lights.Light);
+    method @NonNull public android.hardware.lights.LightsRequest.Builder setLight(@NonNull android.hardware.lights.Light, @NonNull android.hardware.lights.LightState);
+  }
+
+}
+
 package android.location {
 
   public final class GnssClock implements android.os.Parcelable {
@@ -1145,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);
@@ -1156,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);
   }
@@ -1170,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);
@@ -1189,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);
@@ -1399,6 +1457,7 @@
     field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2
     field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1
     field public static final int RULE_MATCH_UID = 4; // 0x4
+    field public static final int RULE_MATCH_USERID = 8; // 0x8
   }
 
   public static class AudioMixingRule.Builder {
@@ -1419,9 +1478,11 @@
     method public int getFocusDuckingBehavior();
     method public int getStatus();
     method public boolean removeUidDeviceAffinity(int);
+    method public boolean removeUserIdDeviceAffinity(int);
     method public int setFocusDuckingBehavior(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setRegistration(String);
     method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
+    method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
     method public String toLogFriendlyString();
     field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
     field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
@@ -1562,9 +1623,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();
@@ -1664,12 +1728,32 @@
     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";
@@ -1677,6 +1761,7 @@
     field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
     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
@@ -1702,8 +1787,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>);
@@ -1719,6 +1811,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();
@@ -3438,6 +3541,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);
@@ -3454,6 +3558,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);
@@ -3577,6 +3683,7 @@
     field public static final String EXTRA_DIALSTRING = "dialstring";
     field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
     field public static final String EXTRA_EMERGENCY_CALL = "e_call";
+    field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
     field public static final String EXTRA_IS_CALL_PULL = "CallPull";
     field public static final String EXTRA_OEM_EXTRAS = "android.telephony.ims.extra.OEM_EXTRAS";
     field public static final String EXTRA_OI = "oi";
@@ -4054,6 +4161,29 @@
     method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
+  public class RcsUceAdapter {
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isUceSettingEnabled() 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
+  }
+
 }
 
 package android.telephony.ims.feature {
@@ -4315,6 +4445,7 @@
     method public int transact(android.os.Bundle);
     method public int updateCallBarring(int, int, String[]);
     method public int updateCallBarringForServiceClass(int, int, String[], int);
+    method public int updateCallBarringWithPassword(int, int, @Nullable String[], int, @NonNull String);
     method public int updateCallForward(int, int, String, int, int);
     method public int updateCallWaiting(boolean, int);
     method public int updateClip(boolean);
@@ -4602,22 +4733,6 @@
     method public abstract String asyncImpl() default "";
   }
 
-  public class SurfaceControlViewHost {
-    ctor public SurfaceControlViewHost(@NonNull android.content.Context, @NonNull android.view.Display, @Nullable android.os.IBinder);
-    method public void addView(android.view.View, android.view.WindowManager.LayoutParams);
-    method public void dispose();
-    method @Nullable public android.view.SurfaceControlViewHost.SurfacePackage getSurfacePackage();
-    method public void relayout(android.view.WindowManager.LayoutParams);
-  }
-
-  public class SurfaceControlViewHost.SurfacePackage {
-    method @NonNull public android.view.SurfaceControl getSurfaceControl();
-  }
-
-  public class SurfaceView extends android.view.View {
-    method @Nullable public android.os.IBinder getInputToken();
-  }
-
   @UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
     method public android.view.View getTooltipView();
     method public boolean isAutofilled();
@@ -4662,7 +4777,7 @@
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
     field public CharSequence accessibilityTitle;
-    field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="APPEARANCE_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="BEHAVIOR_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x10000000, equals=0x10000000, name="FIT_INSETS_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x20000000, equals=0x20000000, name="ONLY_DRAW_BOTTOM_BAR_BACKGROUND")}) public int privateFlags;
+    field @android.view.ViewDebug.ExportedProperty(flagMapping={@android.view.ViewDebug.FlagToString(mask=0x1, equals=0x1, name="FAKE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x2, equals=0x2, name="FORCE_HARDWARE_ACCELERATED"), @android.view.ViewDebug.FlagToString(mask=0x4, equals=0x4, name="WANTS_OFFSET_NOTIFICATIONS"), @android.view.ViewDebug.FlagToString(mask=0x10, equals=0x10, name="SHOW_FOR_ALL_USERS"), @android.view.ViewDebug.FlagToString(mask=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, equals=android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION, name="NO_MOVE_ANIMATION"), @android.view.ViewDebug.FlagToString(mask=0x80, equals=0x80, name="COMPATIBLE_WINDOW"), @android.view.ViewDebug.FlagToString(mask=0x100, equals=0x100, name="SYSTEM_ERROR"), @android.view.ViewDebug.FlagToString(mask=0x800, equals=0x800, name="DISABLE_WALLPAPER_TOUCH_EVENTS"), @android.view.ViewDebug.FlagToString(mask=0x1000, equals=0x1000, name="FORCE_STATUS_BAR_VISIBLE"), @android.view.ViewDebug.FlagToString(mask=0x2000, equals=0x2000, name="PRESERVE_GEOMETRY"), @android.view.ViewDebug.FlagToString(mask=0x4000, equals=0x4000, name="FORCE_DECOR_VIEW_VISIBILITY"), @android.view.ViewDebug.FlagToString(mask=0x8000, equals=0x8000, name="WILL_NOT_REPLACE_ON_RELAUNCH"), @android.view.ViewDebug.FlagToString(mask=0x10000, equals=0x10000, name="LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), @android.view.ViewDebug.FlagToString(mask=0x20000, equals=0x20000, name="FORCE_DRAW_STATUS_BAR_BACKGROUND"), @android.view.ViewDebug.FlagToString(mask=0x40000, equals=0x40000, name="SUSTAINED_PERFORMANCE_MODE"), @android.view.ViewDebug.FlagToString(mask=0x80000, equals=0x80000, name="HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), @android.view.ViewDebug.FlagToString(mask=0x100000, equals=0x100000, name="IS_ROUNDED_CORNERS_OVERLAY"), @android.view.ViewDebug.FlagToString(mask=0x400000, equals=0x400000, name="IS_SCREEN_DECOR"), @android.view.ViewDebug.FlagToString(mask=0x800000, equals=0x800000, name="STATUS_FORCE_SHOW_NAVIGATION"), @android.view.ViewDebug.FlagToString(mask=0x1000000, equals=0x1000000, name="COLOR_SPACE_AGNOSTIC"), @android.view.ViewDebug.FlagToString(mask=0x4000000, equals=0x4000000, name="APPEARANCE_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x8000000, equals=0x8000000, name="BEHAVIOR_CONTROLLED"), @android.view.ViewDebug.FlagToString(mask=0x10000000, equals=0x10000000, name="FIT_INSETS_CONTROLLED")}) public int privateFlags;
   }
 
 }
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index 54f7f68..a9c1836 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():
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..d9d5be6 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -151,8 +151,8 @@
         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;
@@ -341,6 +341,8 @@
         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;
     }
 
     // Pulled events will start at field 10000.
@@ -1724,6 +1726,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 +8072,43 @@
     // 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;
+}
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..7708e30 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);
@@ -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/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/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/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/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 b82a675..d90e81f 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;
@@ -7326,6 +7283,15 @@
         }
     }
 
+    float getFloatCoreSetting(String key, float defaultValue) {
+        synchronized (mResourcesManager) {
+            if (mCoreSettings != null) {
+                return mCoreSettings.getFloat(key, defaultValue);
+            }
+            return defaultValue;
+        }
+    }
+
     private static class AndroidOs extends ForwardingOs {
         /**
          * Install selective syscall interception. For example, this is used to
@@ -7514,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/AppGlobals.java b/core/java/android/app/AppGlobals.java
index 81e1565..f66bf0d 100644
--- a/core/java/android/app/AppGlobals.java
+++ b/core/java/android/app/AppGlobals.java
@@ -75,4 +75,20 @@
             return defaultValue;
         }
     }
+
+    /**
+     * Gets the value of a float core setting.
+     *
+     * @param key The setting key.
+     * @param defaultValue The setting default value.
+     * @return The core settings.
+     */
+    public static float getFloatCoreSetting(String key, float defaultValue) {
+        ActivityThread currentActivityThread = ActivityThread.currentActivityThread();
+        if (currentActivityThread != null) {
+            return currentActivityThread.getFloatCoreSetting(key, defaultValue);
+        } else {
+            return defaultValue;
+        }
+    }
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index bc7e1e5..46f8669 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1159,6 +1159,7 @@
     @SystemApi
     public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
     /** @hide Read device identifiers */
+    @SystemApi
     public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
     /** @hide Query all packages on device */
     public static final String OPSTR_QUERY_ALL_PACKAGES = "android:query_all_packages";
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..5a4d620 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 =
@@ -632,22 +632,22 @@
     private static final int SYS_FEATURE_CACHE_SIZE = 256;
     private static final String CACHE_KEY_SYS_FEATURE_PROPERTY = "cache_key.has_system_feature";
 
-    private class SystemFeatureQuery {
+    private class HasSystemFeatureQuery {
         public final String name;
         public final int version;
-        public SystemFeatureQuery(String n, int v) {
+        public HasSystemFeatureQuery(String n, int v) {
             name = n;
             version = v;
         }
         @Override
         public String toString() {
-            return String.format("SystemFeatureQuery(name=\"%s\", version=%d)",
+            return String.format("HasSystemFeatureQuery(name=\"%s\", version=%d)",
                     name, version);
         }
         @Override
         public boolean equals(Object o) {
-            if (o instanceof SystemFeatureQuery) {
-                SystemFeatureQuery r = (SystemFeatureQuery) o;
+            if (o instanceof HasSystemFeatureQuery) {
+                HasSystemFeatureQuery r = (HasSystemFeatureQuery) o;
                 return Objects.equals(name, r.name) &&  version == r.version;
             } else {
                 return false;
@@ -655,32 +655,32 @@
         }
         @Override
         public int hashCode() {
-            return Objects.hashCode(name) + version;
+            return Objects.hashCode(name) * 13 + version;
         }
     }
 
-    private final PropertyInvalidatedCache<SystemFeatureQuery, Boolean> mSysFeatureCache =
-            new PropertyInvalidatedCache<SystemFeatureQuery, Boolean>(
+    private final PropertyInvalidatedCache<HasSystemFeatureQuery, Boolean> mHasSystemFeatureCache =
+            new PropertyInvalidatedCache<>(
                 SYS_FEATURE_CACHE_SIZE,
                 CACHE_KEY_SYS_FEATURE_PROPERTY) {
                 @Override
-                protected Boolean recompute(SystemFeatureQuery query) {
+                protected Boolean recompute(HasSystemFeatureQuery query) {
                     return hasSystemFeatureUncached(query.name, query.version);
                 }
             };
 
     @Override
     public boolean hasSystemFeature(String name, int version) {
-        return mSysFeatureCache.query(new SystemFeatureQuery(name, version)).booleanValue();
+        return mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version));
     }
 
     /** @hide */
-    public void disableSysFeatureCache() {
-        mSysFeatureCache.disableLocal();
+    public void disableHasSystemFeatureCache() {
+        mHasSystemFeatureCache.disableLocal();
     }
 
     /** @hide */
-    public static void invalidateSysFeatureCache() {
+    public static void invalidateHasSystemFeatureCache() {
         PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SYS_FEATURE_PROPERTY);
     }
 
@@ -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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index cd84310..b7555ee 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.AutofillOptions;
 import android.content.BroadcastReceiver;
@@ -201,7 +200,7 @@
     @UnsupportedAppUsage
     private @Nullable ClassLoader mClassLoader;
 
-    private final @Nullable IBinder mActivityToken;
+    private final @Nullable IBinder mToken;
 
     private final @NonNull UserHandle mUser;
 
@@ -219,7 +218,7 @@
     private final @NonNull ResourcesManager mResourcesManager;
     @UnsupportedAppUsage
     private @NonNull Resources mResources;
-    private @Nullable Display mDisplay; // may be null if default display
+    private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet.
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private final int mFlags;
@@ -244,6 +243,9 @@
 
     private final Object mSync = new Object();
 
+    private boolean mIsSystemOrSystemUiContext;
+    private boolean mIsUiContext;
+
     @GuardedBy("mSync")
     private File mDatabasesDir;
     @GuardedBy("mSync")
@@ -1883,6 +1885,9 @@
 
     @Override
     public Object getSystemService(String name) {
+        if (isUiComponent(name) && !isUiContext()) {
+            Log.w(TAG, name + " should be accessed from Activity or other visual Context");
+        }
         return SystemServiceRegistry.getSystemService(this, name);
     }
 
@@ -1891,6 +1896,15 @@
         return SystemServiceRegistry.getSystemServiceName(serviceClass);
     }
 
+    boolean isUiContext() {
+        return mIsSystemOrSystemUiContext || mIsUiContext;
+    }
+
+    private static boolean isUiComponent(String name) {
+        return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name)
+                || WALLPAPER_SERVICE.equals(name);
+    }
+
     @Override
     public int checkPermission(String permission, int pid, int uid) {
         if (permission == null) {
@@ -2229,12 +2243,12 @@
         LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE);
         if (pi != null) {
-            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mActivityToken,
+            ContextImpl c = new ContextImpl(this, mMainThread, pi, null, null, mToken,
                     new UserHandle(UserHandle.getUserId(application.uid)), flags, null, null);
 
             final int displayId = getDisplayId();
 
-            c.setResources(createResources(mActivityToken, pi, null, displayId, null,
+            c.setResources(createResources(mToken, pi, null, displayId, null,
                     getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
@@ -2258,18 +2272,18 @@
             // The system resources are loaded in every application, so we can safely copy
             // the context without reloading Resources.
             return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null,
-                    mActivityToken, user, flags, null, null);
+                    mToken, user, flags, null, null);
         }
 
         LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
                 flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
         if (pi != null) {
             ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null,
-                    mActivityToken, user, flags, null, null);
+                    mToken, user, flags, null, null);
 
             final int displayId = getDisplayId();
 
-            c.setResources(createResources(mActivityToken, pi, null, displayId, null,
+            c.setResources(createResources(mToken, pi, null, displayId, null,
                     getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
@@ -2301,12 +2315,12 @@
         final String[] paths = mPackageInfo.getSplitPaths(splitName);
 
         final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
-                mFeatureId, splitName, mActivityToken, mUser, mFlags, classLoader, null);
+                mFeatureId, splitName, mToken, mUser, mFlags, classLoader, null);
 
         final int displayId = getDisplayId();
 
         context.setResources(ResourcesManager.getInstance().getResources(
-                mActivityToken,
+                mToken,
                 mPackageInfo.getResDir(),
                 paths,
                 mPackageInfo.getOverlayDirs(),
@@ -2325,10 +2339,10 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
-                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
+                mSplitName, mToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = getDisplayId();
-        context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
+        context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
                 overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
         return context;
     }
@@ -2340,19 +2354,36 @@
         }
 
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
-                mSplitName, mActivityToken, mUser, mFlags, mClassLoader, null);
+                mSplitName, mToken, mUser, mFlags, mClassLoader, null);
 
         final int displayId = display.getDisplayId();
-        context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId,
+        context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
                 null, getDisplayAdjustments(displayId).getCompatibilityInfo()));
         context.mDisplay = display;
         return context;
     }
 
     @Override
+    public @NonNull WindowContext createWindowContext(int type) {
+        if (getDisplay() == null) {
+            throw new UnsupportedOperationException("WindowContext can only be created from "
+                    + "other visual contexts, such as Activity or one created with "
+                    + "Context#createDisplayContext(Display)");
+        }
+        return new WindowContext(this, null /* token */, type);
+    }
+
+    ContextImpl createBaseWindowContext(IBinder token) {
+        ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+                mSplitName, token, mUser, mFlags, mClassLoader, null);
+        context.mIsUiContext = true;
+        return context;
+    }
+
+    @Override
     public @NonNull Context createFeatureContext(@Nullable String featureId) {
         return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName,
-                mActivityToken, mUser, mFlags, mClassLoader, null);
+                mToken, mUser, mFlags, mClassLoader, null);
     }
 
     @Override
@@ -2360,7 +2391,7 @@
         final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
                 | Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
-                mActivityToken, mUser, flags, mClassLoader, null);
+                mToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
@@ -2368,7 +2399,7 @@
         final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
                 | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
         return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
-                mActivityToken, mUser, flags, mClassLoader, null);
+                mToken, mUser, flags, mClassLoader, null);
     }
 
     @Override
@@ -2394,8 +2425,6 @@
         return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0;
     }
 
-    @UnsupportedAppUsage
-    @TestApi
     @Override
     public Display getDisplay() {
         if (mDisplay == null) {
@@ -2408,7 +2437,8 @@
 
     @Override
     public int getDisplayId() {
-        return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
+        final Display display = getDisplay();
+        return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY;
     }
 
     @Override
@@ -2518,6 +2548,7 @@
         context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
+        context.mIsSystemOrSystemUiContext = true;
         return context;
     }
 
@@ -2535,6 +2566,7 @@
         context.setResources(createResources(null, packageInfo, null, displayId, null,
                 packageInfo.getCompatibilityInfo()));
         context.updateDisplay(displayId);
+        context.mIsSystemOrSystemUiContext = true;
         return context;
     }
 
@@ -2584,6 +2616,7 @@
 
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
                 activityInfo.splitName, activityToken, null, 0, classLoader, null);
+        context.mIsUiContext = true;
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
         displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
@@ -2629,7 +2662,7 @@
         }
 
         mMainThread = mainThread;
-        mActivityToken = activityToken;
+        mToken = activityToken;
         mFlags = flags;
 
         if (user == null) {
@@ -2649,6 +2682,7 @@
             opPackageName = container.mOpPackageName;
             setResources(container.mResources);
             mDisplay = container.mDisplay;
+            mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext;
         } else {
             mBasePackageName = packageInfo.mPackageName;
             ApplicationInfo ainfo = packageInfo.getApplicationInfo();
@@ -2710,7 +2744,7 @@
     @Override
     @UnsupportedAppUsage
     public IBinder getActivityToken() {
-        return mActivityToken;
+        return mToken;
     }
 
     private void checkMode(int mode) {
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/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/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c1e5356..f170b5d 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -89,6 +89,7 @@
 import android.hardware.input.InputManager;
 import android.hardware.iris.IIrisService;
 import android.hardware.iris.IrisManager;
+import android.hardware.lights.LightsManager;
 import android.hardware.location.ContextHubManager;
 import android.hardware.radio.RadioManager;
 import android.hardware.usb.IUsbManager;
@@ -106,6 +107,7 @@
 import android.media.soundtrigger.SoundTriggerManager;
 import android.media.tv.ITvInputManager;
 import android.media.tv.TvInputManager;
+import android.net.ConnectivityDiagnosticsManager;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityThread;
 import android.net.EthernetManager;
@@ -120,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;
@@ -148,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;
@@ -376,6 +380,27 @@
                 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>() {
+            @Override
+            public ConnectivityDiagnosticsManager createService(ContextImpl ctx)
+                    throws ServiceNotFoundException {
+                // ConnectivityDiagnosticsManager is backed by ConnectivityService
+                IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE);
+                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
+                return new ConnectivityDiagnosticsManager(ctx, service);
+            }});
+
         registerService(
                 Context.TEST_NETWORK_SERVICE,
                 TestNetworkManager.class,
@@ -587,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
@@ -1262,6 +1280,13 @@
                                 Context.DATA_LOADER_MANAGER_SERVICE);
                         return new DataLoaderManager(IDataLoaderManager.Stub.asInterface(b));
                     }});
+        registerService(Context.LIGHTS_SERVICE, LightsManager.class,
+            new CachedServiceFetcher<LightsManager>() {
+                @Override
+                public LightsManager createService(ContextImpl ctx)
+                    throws ServiceNotFoundException {
+                    return new LightsManager(ctx);
+                }});
         //TODO(b/136132412): refactor this: 1) merge IIncrementalManager.aidl and
         //IIncrementalManagerNative.aidl, 2) implement the binder interface in
         //IncrementalManagerService.java, 3) use JNI to call native functions
@@ -1306,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/WindowContext.java b/core/java/android/app/WindowContext.java
new file mode 100644
index 0000000..22cc14b
--- /dev/null
+++ b/core/java/android/app/WindowContext.java
@@ -0,0 +1,123 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.WindowManagerImpl;
+
+/**
+ * {@link WindowContext} is a context for non-activity windows such as
+ * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} windows or system
+ * windows. Its resources and configuration are adjusted to the area of the display that will be
+ * used when a new window is added via {@link android.view.WindowManager.addView}.
+ *
+ * @see Context#createWindowContext(int)
+ * @hide
+ */
+// TODO(b/128338354): Handle config/display changes from server side.
+public class WindowContext extends ContextWrapper {
+    private final WindowManagerImpl mWindowManager;
+    private final IWindowManager mWms;
+    private final IBinder mToken;
+    private final int mDisplayId;
+    private boolean mOwnsToken;
+
+    /**
+     * Default constructor. Can either accept an existing token or generate one and registers it
+     * with the server if necessary.
+     *
+     * @param base Base {@link Context} for this new instance.
+     * @param token A valid {@link com.android.server.wm.WindowToken}. Pass {@code null} to generate
+     *              one.
+     * @param type Window type to be used with this context.
+     * @hide
+     */
+    public WindowContext(Context base, IBinder token, int type) {
+        super(null /* base */);
+
+        mWms = WindowManagerGlobal.getWindowManagerService();
+        if (token != null && !isWindowToken(token)) {
+            throw new IllegalArgumentException("Token must be registered to server.");
+        }
+
+        final ContextImpl contextImpl = createBaseWindowContext(base, token);
+        attachBaseContext(contextImpl);
+        contextImpl.setOuterContext(this);
+
+        mToken = token != null ? token : new Binder();
+        mDisplayId = getDisplayId();
+        mWindowManager = new WindowManagerImpl(this);
+        mWindowManager.setDefaultToken(mToken);
+
+        // TODO(b/128338354): Obtain the correct config from WM and adjust resources.
+        if (token != null) {
+            mOwnsToken = false;
+            return;
+        }
+        try {
+            mWms.addWindowContextToken(mToken, type, mDisplayId, getPackageName());
+            // TODO(window-context): remove token with a DeathObserver
+        }  catch (RemoteException e) {
+            mOwnsToken = false;
+            throw e.rethrowFromSystemServer();
+        }
+        mOwnsToken = true;
+    }
+
+    /** Check if the passed window token is registered with the server. */
+    private boolean isWindowToken(@NonNull IBinder token) {
+        try {
+            return mWms.isWindowToken(token);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+        return false;
+    }
+
+    private static ContextImpl createBaseWindowContext(Context outer, IBinder token) {
+        final ContextImpl contextImpl = ContextImpl.getImpl(outer);
+        return contextImpl.createBaseWindowContext(token);
+    }
+
+    @Override
+    public Object getSystemService(String name) {
+        if (WINDOW_SERVICE.equals(name)) {
+            return mWindowManager;
+        }
+        return super.getSystemService(name);
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        if (mOwnsToken) {
+            try {
+                mWms.removeWindowToken(mToken, mDisplayId);
+                mOwnsToken = false;
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        super.finalize();
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1bf6c99..d1b5a83 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2391,6 +2391,36 @@
             "android.app.action.BIND_SECONDARY_LOCKSCREEN_SERVICE";
 
     /**
+     * Return value for {@link #getPersonalAppsSuspendedReasons} when personal apps are not
+     * suspended.
+     */
+    public static final int PERSONAL_APPS_NOT_SUSPENDED = 0;
+
+    /**
+     * Flag for {@link #getPersonalAppsSuspendedReasons} return value. Set when personal
+     * apps are suspended by an admin explicitly via {@link #setPersonalAppsSuspended}.
+     */
+    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_PROFILE_TIMEOUT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PersonalAppSuspensionReason {}
+
+    /**
      * Return true if the given administrator component is currently active (enabled) in the system.
      *
      * @param admin The administrator component to check for.
@@ -4577,6 +4607,18 @@
             = "android.app.action.START_ENCRYPTION";
 
     /**
+     * Activity action: launch the DPC to check policy compliance. This intent is launched when
+     * the user taps on the notification about personal apps suspension. When handling this intent
+     * the DPC must check if personal apps should still be suspended and either unsuspend them or
+     * instruct the user on how to resolve the noncompliance causing the suspension.
+     *
+     * @see #setPersonalAppsSuspended
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CHECK_POLICY_COMPLIANCE =
+            "android.app.action.CHECK_POLICY_COMPLIANCE";
+
+    /**
      * Broadcast action: notify managed provisioning that new managed user is created.
      *
      * @hide
@@ -8226,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.
@@ -8233,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();
             }
@@ -8255,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();
             }
@@ -8795,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.
@@ -9057,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
@@ -9075,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.
@@ -9334,6 +9439,16 @@
      * {@link android.os.Build.VERSION_CODES#M} the app-op matching the permission is set to
      * {@link android.app.AppOpsManager#MODE_IGNORED}, but the permission stays granted.
      *
+     * NOTE: Starting from Android R, location-related permissions cannot be granted by the
+     * admin: Calling this method with {@link #PERMISSION_GRANT_STATE_GRANTED} for any of the
+     * following permissions will return false:
+     *
+     * <ul>
+     * <li>{@code ACCESS_FINE_LOCATION}</li>
+     * <li>{@code ACCESS_BACKGROUND_LOCATION}</li>
+     * <li>{@code ACCESS_COARSE_LOCATION}</li>
+     * </ul>
+     *
      * @param admin Which profile or device owner this request is associated with.
      * @param packageName The application to grant or revoke a permission to.
      * @param permission The permission to grant or revoke.
@@ -11150,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
@@ -11665,4 +11781,98 @@
         }
         return false;
     }
+
+    /**
+     * Called by profile owner of an organization-owned managed profile to check whether
+     * personal apps are suspended.
+     *
+     * @return a bitmask of reasons for personal apps suspension or
+     *     {@link #PERSONAL_APPS_NOT_SUSPENDED} if apps are not suspended.
+     * @see #setPersonalAppsSuspended
+     */
+    public @PersonalAppSuspensionReason int getPersonalAppsSuspendedReasons(
+            @NonNull ComponentName admin) {
+        throwIfParentInstance("getPersonalAppsSuspendedReasons");
+        if (mService != null) {
+            try {
+                return mService.getPersonalAppsSuspendedReasons(admin);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Called by a profile owner of an organization-owned managed profile to suspend personal
+     * apps on the device. When personal apps are suspended the device can only be used for calls.
+     *
+     * <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 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");
+        if (mService != null) {
+            try {
+                mService.setPersonalAppsSuspended(admin, suspended);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * 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 e7667c0..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);
@@ -470,4 +471,10 @@
 
     void setCommonCriteriaModeEnabled(in ComponentName admin, boolean enabled);
     boolean isCommonCriteriaModeEnabled(in ComponentName admin);
+
+    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/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 3107c63..d4b5b1a 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -269,7 +269,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
-    public boolean isDeviceAssociated(
+    public boolean isDeviceAssociatedForWifiConnection(
             @NonNull String packageName,
             @NonNull MacAddress macAddress,
             @NonNull UserHandle user) {
@@ -280,7 +280,7 @@
         Objects.requireNonNull(macAddress, "mac address cannot be null");
         Objects.requireNonNull(user, "user cannot be null");
         try {
-            return mService.isDeviceAssociated(
+            return mService.isDeviceAssociatedForWifiConnection(
                     packageName, macAddress.toString(), user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 2e1ff0b..b323f58 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -40,5 +40,6 @@
     boolean hasNotificationAccess(in ComponentName component);
     PendingIntent requestNotificationAccess(in ComponentName component);
 
-    boolean isDeviceAssociated(in String packageName, in String macAddress, int userId);
+    boolean isDeviceAssociatedForWifiConnection(in String packageName, in String macAddress,
+        int userId);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2943e39..58a0ea5 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,
@@ -3480,6 +3481,7 @@
             //@hide: TIME_DETECTOR_SERVICE,
             //@hide: TIME_ZONE_DETECTOR_SERVICE,
             PERMISSION_SERVICE,
+            LIGHTS_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -3983,6 +3985,24 @@
     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.
+     *
+     * @see #getSystemService(String)
+     * @see android.net.ConnectivityDiagnosticsManager
+     */
+    public static final String CONNECTIVITY_DIAGNOSTICS_SERVICE = "connectivity_diagnostics";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a {@link
      * android.net.TestNetworkManager} for building TUNs and limited-use Networks
      *
@@ -5111,6 +5131,15 @@
     public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.hardware.lights.LightsManager} for controlling device lights.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    public static final String LIGHTS_SERVICE = "lights";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
@@ -5720,6 +5749,63 @@
     public abstract Context createDisplayContext(@NonNull Display display);
 
     /**
+     * Creates a Context for a non-activity window.
+     *
+     * <p>
+     * A window context is a context that can be used to add non-activity windows, such as
+     * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY}. A window context
+     * must be created from a context that has an associated {@link Display}, such as
+     * {@link android.app.Activity Activity} or a context created with
+     * {@link #createDisplayContext(Display)}.
+     *
+     * <p>
+     * The window context is created with the appropriate {@link Configuration} for the area of the
+     * display that the windows created with it can occupy; it must be used when
+     * {@link android.view.LayoutInflater inflating} views, such that they can be inflated with
+     * proper {@link Resources}.
+     *
+     * Below is a sample code to <b>add an application overlay window on the primary display:<b/>
+     * <pre class="prettyprint">
+     * ...
+     * final DisplayManager dm = anyContext.getSystemService(DisplayManager.class);
+     * final Display primaryDisplay = dm.getDisplay(DEFAULT_DISPLAY);
+     * final Context windowContext = anyContext.createDisplayContext(primaryDisplay)
+     *         .createWindowContext(TYPE_APPLICATION_OVERLAY);
+     * final View overlayView = Inflater.from(windowContext).inflate(someLayoutXml, null);
+     *
+     * // WindowManager.LayoutParams initialization
+     * ...
+     * mParams.type = TYPE_APPLICATION_OVERLAY;
+     * ...
+     *
+     * mWindowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
+     * </pre>
+     *
+     * <p>
+     * This context's configuration and resources are adjusted to a display area where the windows
+     * with provided type will be added. <b>Note that all windows associated with the same context
+     * will have an affinity and can only be moved together between different displays or areas on a
+     * display.</b> If there is a need to add different window types, or non-associated windows,
+     * separate Contexts should be used.
+     * </p>
+     *
+     * @param type Window type in {@link WindowManager.LayoutParams}
+     * @return A {@link Context} that can be used to create windows.
+     * @throws UnsupportedOperationException if this is called on a non-UI context, such as
+     *         {@link android.app.Application Application} or {@link android.app.Service Service}.
+     *
+     * @see #getSystemService(String)
+     * @see #getSystemService(Class)
+     * @see #WINDOW_SERVICE
+     * @see #LAYOUT_INFLATER_SERVICE
+     * @see #WALLPAPER_SERVICE
+     * @throws IllegalArgumentException if token is invalid
+     */
+    public @NonNull Context createWindowContext(int type)  {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Return a new Context object for the current Context but for a different feature in the app.
      * Features can be used by complex apps to separate logical parts.
      *
@@ -5803,17 +5889,22 @@
     public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
 
     /**
+     * Get the display this context is associated with. Applications should use this method with
+     * {@link android.app.Activity} or a context associated with a {@link Display} via
+     * {@link #createDisplayContext(Display)} to get a display object associated with a Context, or
+     * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id.
      * @return Returns the {@link Display} object this context is associated with.
-     * @hide
      */
-    @UnsupportedAppUsage
-    @TestApi
-    public abstract Display getDisplay();
+    @Nullable
+    public Display getDisplay() {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
 
     /**
-     * Gets the display ID.
+     * Gets the ID of the display this context is associated with.
      *
      * @return display ID associated with this {@link Context}.
+     * @see #getDisplay()
      * @hide
      */
     @TestApi
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 6fe1187..b2b7988 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -977,6 +977,12 @@
     }
 
     @Override
+    @NonNull
+    public Context createWindowContext(int type) {
+        return mBase.createWindowContext(type);
+    }
+
+    @Override
     public @NonNull Context createFeatureContext(@Nullable String featureId) {
         return mBase.createFeatureContext(featureId);
     }
@@ -992,11 +998,8 @@
         return mBase.getDisplayAdjustments(displayId);
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    @TestApi
     @Override
-    public Display getDisplay() {
+    public @Nullable Display getDisplay() {
         return mBase.getDisplay();
     }
 
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%
rename from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
rename 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/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 f264adb..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();
             }
@@ -2029,6 +2095,9 @@
         public boolean isCommitted;
 
         /** {@hide} */
+        public long createdMillis;
+
+        /** {@hide} */
         public long updatedMillis;
 
         /** {@hide} */
@@ -2078,6 +2147,7 @@
             mStagedSessionErrorMessage = source.readString();
             isCommitted = source.readBoolean();
             rollbackDataPolicy = source.readInt();
+            createdMillis = source.readLong();
         }
 
         /**
@@ -2520,6 +2590,13 @@
         }
 
         /**
+         * The timestamp of the initial creation of the session.
+         */
+        public long getCreatedMillis() {
+            return createdMillis;
+        }
+
+        /**
          * The timestamp of the last update that occurred to the session, including changing of
          * states in case of staged sessions.
          */
@@ -2568,6 +2645,7 @@
             dest.writeString(mStagedSessionErrorMessage);
             dest.writeBoolean(isCommitted);
             dest.writeInt(rollbackDataPolicy);
+            dest.writeLong(createdMillis);
         }
 
         public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a2d425b..66a2b7a 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;
 
     /**
@@ -3328,6 +3329,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 +3527,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 +3582,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 +3608,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 +3629,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 +3876,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 +3903,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 +4026,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 +4044,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 +4063,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 +4609,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 +4620,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 +4629,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 +4642,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 +6668,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 fd4c265..dbfc650 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/ProcessInfo.java b/core/java/android/content/pm/ProcessInfo.java
new file mode 100644
index 0000000..c77a267
--- /dev/null
+++ b/core/java/android/content/pm/ProcessInfo.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 android.content.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+/**
+ * Information about a process an app may run.  This corresponds to information collected from the
+ * AndroidManifest.xml's &lt;permission-group&gt; tags.
+ * @hide
+ */
+public class ProcessInfo implements Parcelable {
+    /**
+     * The name of the process, fully-qualified based on the app's package name.
+     */
+    public String name;
+
+    /**
+     * If non-null, these are permissions that are not allowed in this process.
+     */
+    @Nullable
+    public ArraySet<String> deniedPermissions;
+
+    public ProcessInfo(String name, ArraySet<String> deniedPermissions) {
+        this.name = name;
+        this.deniedPermissions = deniedPermissions;
+    }
+
+    @Deprecated
+    public ProcessInfo(@NonNull ProcessInfo orig) {
+        this.name = orig.name;
+        this.deniedPermissions = orig.deniedPermissions;
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        dest.writeString(this.name);
+        final int numDenied = this.deniedPermissions != null
+                ? this.deniedPermissions.size() : 0;
+        dest.writeInt(numDenied);
+        for (int i = 0; i < numDenied; i++) {
+            dest.writeString(this.deniedPermissions.valueAt(i));
+        }
+    }
+
+    public static final @NonNull Creator<ProcessInfo> CREATOR =
+            new Creator<ProcessInfo>() {
+                public ProcessInfo createFromParcel(Parcel source) {
+                    return new ProcessInfo(source);
+                }
+                public ProcessInfo[] newArray(int size) {
+                    return new ProcessInfo[size];
+                }
+            };
+
+    private ProcessInfo(Parcel source) {
+        this.name = source.readString();
+        final int numDenied = source.readInt();
+        if (numDenied > 0) {
+            this.deniedPermissions = new ArraySet<>(numDenied);
+            for (int i = numDenied - 1; i >= 0; i--) {
+                this.deniedPermissions.add(TextUtils.safeIntern(source.readString()));
+            }
+        }
+    }
+}
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/parsing/AndroidPackage.java b/core/java/android/content/pm/parsing/AndroidPackage.java
index 990c835..fbe5a48 100644
--- a/core/java/android/content/pm/parsing/AndroidPackage.java
+++ b/core/java/android/content/pm/parsing/AndroidPackage.java
@@ -36,6 +36,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -379,6 +380,9 @@
     @Nullable
     long[] getUsesStaticLibrariesVersions();
 
+    @Nullable
+    ArrayMap<String, ComponentParseUtils.ParsedProcess> getProcesses();
+
     int getVersionCode();
 
     int getVersionCodeMajor();
diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java
index 9b069ac..3018230 100644
--- a/core/java/android/content/pm/parsing/ApkParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkParseUtils.java
@@ -2426,6 +2426,21 @@
                     XmlUtils.skipCurrentTag(parser);
 
                     break;
+                case "processes":
+                    ArrayMap<String, ComponentParseUtils.ParsedProcess> processes =
+                            ComponentParseUtils.parseProcesses(separateProcesses,
+                                    parsingPackage,
+                                    res, parser, flags,
+                                    outError);
+                    if (processes == null) {
+                        return parseInput.error(
+                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                                outError[0]
+                        );
+                    }
+
+                    parsingPackage.setProcesses(processes);
+                    break;
                 case "uses-package":
                     // Dependencies for app installers; we don't currently try to
                     // enforce this.
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
index 3846202a..9a0a6d5 100644
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java
@@ -50,6 +50,7 @@
 import android.os.Parcelable;
 import android.os.PatternMatcher;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -1366,6 +1367,72 @@
                 };
     }
 
+    public static class ParsedProcess implements Parcelable {
+
+        public String name;
+        @Nullable
+        public ArraySet<String> deniedPermissions;
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(this.name);
+            final int numDenied = this.deniedPermissions != null
+                    ? this.deniedPermissions.size() : 0;
+            dest.writeInt(numDenied);
+            for (int i = 0; i < numDenied; i++) {
+                dest.writeString(this.deniedPermissions.valueAt(i));
+            }
+        }
+
+        public ParsedProcess() {
+        }
+
+        public ParsedProcess(@NonNull ParsedProcess other) {
+            name = other.name;
+            if (other.deniedPermissions != null) {
+                deniedPermissions = new ArraySet<>(other.deniedPermissions);
+            }
+        }
+
+        public void addStateFrom(@NonNull ParsedProcess other) {
+            if (other.deniedPermissions != null) {
+                for (int i = other.deniedPermissions.size() - 1; i >= 0; i--) {
+                    if (deniedPermissions == null) {
+                        deniedPermissions = new ArraySet<>(other.deniedPermissions.size());
+                    }
+                    deniedPermissions.add(other.deniedPermissions.valueAt(i));
+                }
+            }
+        }
+
+        protected ParsedProcess(Parcel in) {
+            this.name = TextUtils.safeIntern(in.readString());
+            final int numDenied = in.readInt();
+            if (numDenied > 0) {
+                this.deniedPermissions = new ArraySet<>(numDenied);
+                this.deniedPermissions.add(TextUtils.safeIntern(in.readString()));
+            }
+        }
+
+        public static final Creator<ParsedProcess> CREATOR =
+                new Creator<ParsedProcess>() {
+                    @Override
+                    public ParsedProcess createFromParcel(Parcel source) {
+                        return new ParsedProcess(source);
+                    }
+
+                    @Override
+                    public ParsedProcess[] newArray(int size) {
+                        return new ParsedProcess[size];
+                    }
+                };
+    }
+
     public static ParsedActivity parseActivity(
             String[] separateProcesses,
             ParsingPackage parsingPackage,
@@ -3266,6 +3333,189 @@
         return result;
     }
 
+    private static @Nullable ArraySet<String> parseDenyPermission(
+            ArraySet<String> perms,
+            Resources res,
+            XmlResourceParser parser,
+            String[] outError
+    ) throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestDenyPermission);
+        if (sa == null) {
+            outError[0] = "<deny-permission> could not be parsed";
+            return null;
+        }
+
+        try {
+            String perm = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestDenyPermission_name,0);
+            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)) {
+                if (perms == null) {
+                    perms = new ArraySet<>();
+                }
+                perms.add(perm);
+            }
+        } finally {
+            sa.recycle();
+        }
+        XmlUtils.skipCurrentTag(parser);
+        return perms;
+    }
+
+    private static ArraySet<String> parseAllowPermission(
+            ArraySet<String> perms,
+            Resources res,
+            XmlResourceParser parser,
+            String[] outError
+    ) throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestAllowPermission);
+        if (sa == null) {
+            outError[0] = "<allow-permission> could not be parsed";
+            return null;
+        }
+
+        try {
+            String perm = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestAllowPermission_name,0);
+            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)
+                    && perms != null) {
+                perms.remove(perm);
+                if (perms.size() <= 0) {
+                    perms = null;
+                }
+            }
+        } finally {
+            sa.recycle();
+        }
+        XmlUtils.skipCurrentTag(parser);
+        return perms;
+    }
+
+    public static ParsedProcess parseProcess(
+            ArraySet<String> perms,
+            String[] separateProcesses,
+            ParsingPackage parsingPackage,
+            Resources res,
+            XmlResourceParser parser,
+            int flags,
+            String[] outError
+    ) throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProcess);
+        if (sa == null) {
+            outError[0] = "<process> could not be parsed";
+            return null;
+        }
+
+        ParsedProcess proc = new ParsedProcess();
+        if (perms != null) {
+            proc.deniedPermissions = new ArraySet(perms);
+        }
+
+        try {
+            proc.name = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestProcess_process,0);
+            proc.name = PackageParser.buildProcessName(parsingPackage.getPackageName(),
+                    null, proc.name, flags, separateProcesses, outError);
+
+            if (proc.name == null || proc.name.length() <= 0) {
+                outError[0] = "<process> does not specify android:process";
+                return null;
+            }
+            proc.name = PackageParser.buildProcessName(parsingPackage.getPackageName(),
+                    parsingPackage.getPackageName(), proc.name,
+                    flags, separateProcesses, outError);
+            if (outError[0] != null) {
+                return null;
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        int type;
+        final int innerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("deny-permission")) {
+                proc.deniedPermissions = parseDenyPermission(proc.deniedPermissions, res, parser,
+                        outError);
+                if (outError[0] != null) {
+                    return null;
+                }
+            } else if (tagName.equals("allow-permission")) {
+                proc.deniedPermissions = parseAllowPermission(proc.deniedPermissions, res, parser,
+                        outError);
+                if (outError[0] != null) {
+                    return null;
+                }
+            } else {
+                Slog.w(TAG, "Unknown element under <process>: " + tagName
+                        + " at " + parsingPackage.getBaseCodePath() + " "
+                        + parser.getPositionDescription());
+                XmlUtils.skipCurrentTag(parser);
+                continue;
+            }
+        }
+
+        return proc;
+    }
+
+    public static ArrayMap<String, ParsedProcess> parseProcesses(
+            String[] separateProcesses,
+            ParsingPackage parsingPackage,
+            Resources res,
+            XmlResourceParser parser,
+            int flags,
+            String[] outError
+    ) throws IOException, XmlPullParserException {
+        ArraySet<String> deniedPerms = null;
+        ArrayMap<String, ParsedProcess> processes = new ArrayMap<>();
+
+        int type;
+        final int innerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("deny-permission")) {
+                deniedPerms = parseDenyPermission(deniedPerms, res, parser, outError);
+                if (outError[0] != null) {
+                    return null;
+                }
+            } else if (tagName.equals("allow-permission")) {
+                deniedPerms = parseAllowPermission(deniedPerms, res, parser, outError);
+                if (outError[0] != null) {
+                    return null;
+                }
+            } else if (tagName.equals("process")) {
+                ParsedProcess proc = parseProcess(deniedPerms, separateProcesses, parsingPackage,
+                        res, parser, flags, outError);
+                if (outError[0] != null) {
+                    return null;
+                }
+                if (processes.get(proc.name) != null) {
+                    outError[0] = "<process> specified existing name '" + proc.name + "'";
+                    return null;
+                }
+                processes.put(proc.name, proc);
+            } else {
+                Slog.w(TAG, "Unknown element under <processes>: " + tagName
+                        + " at " + parsingPackage.getBaseCodePath() + " "
+                        + parser.getPositionDescription());
+                XmlUtils.skipCurrentTag(parser);
+                continue;
+            }
+        }
+
+        return processes;
+    }
+
     public static ActivityInfo.WindowLayout parseLayout(Resources res, AttributeSet attrs) {
         TypedArray sw = res.obtainAttributes(attrs,
                 R.styleable.AndroidManifestLayout);
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
index 8677fce..9baf325 100644
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ b/core/java/android/content/pm/parsing/PackageImpl.java
@@ -215,6 +215,9 @@
     @Nullable
     private ArrayList<String> queriesPackages;
 
+    @Nullable
+    private ArrayMap<String, ComponentParseUtils.ParsedProcess> processes;
+
     private String[] splitClassLoaderNames;
     private String[] splitCodePaths;
     private SparseArray<int[]> splitDependencies;
@@ -527,6 +530,12 @@
         return usesStaticLibraries;
     }
 
+    @Nullable
+    @Override
+    public ArrayMap<String, ComponentParseUtils.ParsedProcess> getProcesses() {
+        return processes;
+    }
+
     @Override
     public boolean isBaseHardwareAccelerated() {
         return baseHardwareAccelerated;
@@ -948,6 +957,12 @@
     }
 
     @Override
+    public PackageImpl setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes) {
+        this.processes = processes;
+        return this;
+    }
+
+    @Override
     public PackageImpl setSupportsSmallScreens(int supportsSmallScreens) {
         if (supportsSmallScreens == 1) {
             return this;
@@ -3010,6 +3025,11 @@
         dest.writeStringList(this.usesOptionalLibraries);
         dest.writeStringList(this.usesStaticLibraries);
         dest.writeLongArray(this.usesStaticLibrariesVersions);
+        final int numProcesses = this.processes != null ? this.processes.size() : 0;
+        dest.writeInt(numProcesses);
+        for (int i = 0; i < numProcesses; i++) {
+            this.processes.valueAt(i).writeToParcel(dest, 0);
+        }
 
         if (this.usesStaticLibrariesCertDigests == null) {
             dest.writeInt(-1);
@@ -3161,6 +3181,16 @@
         this.usesStaticLibraries = in.createStringArrayList();
         internStringArrayList(usesStaticLibraries);
         this.usesStaticLibrariesVersions = in.createLongArray();
+        final int numProcesses = in.readInt();
+        if (numProcesses > 0) {
+            this.processes = new ArrayMap<>(numProcesses);
+            for (int i = 0; i < numProcesses; i++) {
+                ComponentParseUtils.ParsedProcess proc = new ComponentParseUtils.ParsedProcess(in);
+                this.processes.put(proc.name, proc);
+            }
+        } else {
+            this.processes = null;
+        }
 
         int digestsSize = in.readInt();
         if (digestsSize >= 0) {
diff --git a/core/java/android/content/pm/parsing/PackageInfoUtils.java b/core/java/android/content/pm/parsing/PackageInfoUtils.java
index e0ba99b..72df189 100644
--- a/core/java/android/content/pm/parsing/PackageInfoUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoUtils.java
@@ -32,6 +32,7 @@
 import android.content.pm.PackageUserState;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
+import android.content.pm.ProcessInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.SELinuxUtil;
 import android.content.pm.ServiceInfo;
@@ -41,11 +42,11 @@
 import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
 import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
 import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import com.android.internal.util.ArrayUtils;
 
-import java.util.LinkedHashSet;
 import java.util.Set;
 
 /** @hide */
@@ -459,6 +460,24 @@
         return ii;
     }
 
+    public static ArrayMap<String, ProcessInfo> generateProcessInfo(
+            ArrayMap<String, ComponentParseUtils.ParsedProcess> procs,
+            @PackageManager.ComponentInfoFlags int flags) {
+        if (procs == null) {
+            return null;
+        }
+
+        final int numProcs = procs.size();
+        ArrayMap<String, ProcessInfo> retProcs = new ArrayMap(numProcs);
+        for (int i = 0; i < numProcs; i++) {
+            ComponentParseUtils.ParsedProcess proc = procs.valueAt(i);
+            retProcs.put(proc.name, new ProcessInfo(proc.name,
+                    proc.deniedPermissions != null
+                            ? new ArraySet<>(proc.deniedPermissions) : null));
+        }
+        return retProcs;
+    }
+
     public static PermissionInfo generatePermissionInfo(ParsedPermission p,
             @PackageManager.ComponentInfoFlags int flags) {
         if (p == null) return null;
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 411c749..9ddcc09 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -31,6 +31,7 @@
 import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
 import android.content.pm.parsing.ComponentParseUtils.ParsedService;
 import android.os.Bundle;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -99,6 +100,8 @@
 
     ParsingPackage addQueriesPackage(String packageName);
 
+    ParsingPackage setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes);
+
     ParsingPackage asSplit(
             String[] splitNames,
             String[] splitCodePaths,
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..dfc4f0f 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2860,6 +2860,23 @@
             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>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/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 9b58578..55025f0 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -718,6 +718,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 +960,9 @@
         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>>();
 
         // Registered availablility callbacks and their executors
         private final ArrayMap<AvailabilityCallback, Executor> mCallbackMap =
@@ -1003,6 +1052,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) {
@@ -1086,6 +1143,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
@@ -1236,7 +1297,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 +1305,11 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                callback.onCameraAvailable(id);
+                                if (physicalId == null) {
+                                    callback.onCameraAvailable(id);
+                                } else {
+                                    callback.onPhysicalCameraAvailable(id, physicalId);
+                                }
                             }
                         });
                 } finally {
@@ -1257,7 +1322,11 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                callback.onCameraUnavailable(id);
+                                if (physicalId == null) {
+                                    callback.onCameraUnavailable(id);
+                                } else {
+                                    callback.onPhysicalCameraUnavailable(id, physicalId);
+                                }
                             }
                         });
                 } finally {
@@ -1304,7 +1373,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 +1401,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 +1448,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 +1612,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);
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/lights/ILightsManager.aidl b/core/java/android/hardware/lights/ILightsManager.aidl
new file mode 100644
index 0000000..6ea24b7
--- /dev/null
+++ b/core/java/android/hardware/lights/ILightsManager.aidl
@@ -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 android.hardware.lights;
+
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+
+/**
+ * API to lights manager service.
+ *
+ * {@hide}
+ */
+interface ILightsManager {
+  List<Light> getLights();
+  LightState getLightState(int lightId);
+  void openSession(in IBinder sessionToken);
+  void closeSession(in IBinder sessionToken);
+  void setLightStates(in IBinder sessionToken, in int[] lightIds, in LightState[] states);
+}
diff --git a/core/java/android/service/controls/actions/CommandAction.aidl b/core/java/android/hardware/lights/Light.aidl
similarity index 81%
copy from core/java/android/service/controls/actions/CommandAction.aidl
copy to core/java/android/hardware/lights/Light.aidl
index 7c1ee41..946e06d4 100644
--- a/core/java/android/service/controls/actions/CommandAction.aidl
+++ b/core/java/android/hardware/lights/Light.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,8 @@
  * 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.hardware.lights;
+
+/** @hide */
+parcelable Light;
diff --git a/core/java/android/hardware/lights/Light.java b/core/java/android/hardware/lights/Light.java
new file mode 100644
index 0000000..c5cb803
--- /dev/null
+++ b/core/java/android/hardware/lights/Light.java
@@ -0,0 +1,105 @@
+/**
+ * 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.lights;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a logical light on the device.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class Light implements Parcelable {
+    private final int mId;
+    private final int mOrdinal;
+    private final int mType;
+
+    /**
+     * Creates a new light with the given data.
+     *
+     * @hide */
+    public Light(int id, int ordinal, int type) {
+        mId = id;
+        mOrdinal = ordinal;
+        mType = type;
+    }
+
+    private Light(@NonNull Parcel in) {
+        mId = in.readInt();
+        mOrdinal = in.readInt();
+        mType = in.readInt();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mId);
+        dest.writeInt(mOrdinal);
+        dest.writeInt(mType);
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public static final @android.annotation.NonNull Parcelable.Creator<Light> CREATOR =
+            new Parcelable.Creator<Light>() {
+                public Light createFromParcel(Parcel in) {
+                    return new Light(in);
+                }
+
+                public Light[] newArray(int size) {
+                    return new Light[size];
+                }
+            };
+
+    /**
+     * Returns the id of the light.
+     */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the ordinal of the light.
+     *
+     * <p>This represents the physical order of the lights on the device. The exact values are
+     * device-dependent, but for example, if there are lights in a row, sorting the Light objects
+     * by ordinal should match the order in which they appear on the device. If the device has
+     * 4 lights, the ordinals could be [1, 2, 3, 4] or [0, 10, 20, 30] or any other values that
+     * have the same sort order.
+     */
+    public int getOrdinal() {
+        return mOrdinal;
+    }
+
+    /**
+     * Returns the logical type of the light.
+     */
+    public @LightsManager.LightType int getType() {
+        return mType;
+    }
+}
diff --git a/core/java/android/service/controls/actions/ControlAction.aidl b/core/java/android/hardware/lights/LightState.aidl
similarity index 81%
rename from core/java/android/service/controls/actions/ControlAction.aidl
rename to core/java/android/hardware/lights/LightState.aidl
index b012521..d598336 100644
--- a/core/java/android/service/controls/actions/ControlAction.aidl
+++ b/core/java/android/hardware/lights/LightState.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,7 @@
  * limitations under the License.
  */
 
-package android.service.controls.actions;
+package android.hardware.lights;
 
-parcelable ControlAction;
\ No newline at end of file
+/** @hide */
+parcelable LightState;
diff --git a/core/java/android/hardware/lights/LightState.java b/core/java/android/hardware/lights/LightState.java
new file mode 100644
index 0000000..e55aa70
--- /dev/null
+++ b/core/java/android/hardware/lights/LightState.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.lights;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the state of a device light.
+ *
+ * <p>Controlling the color and brightness of a light is done on a best-effort basis. Each of the R,
+ * G and B channels represent the intensities of the respective part of an RGB LED, if that is
+ * supported. For devices that only support on or off lights, everything that's not off will turn
+ * the light on. If the light is monochrome and only the brightness can be controlled, the RGB color
+ * will be converted to only a brightness value and that will be used for the light's single
+ * channel.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class LightState implements Parcelable {
+    private final int mColor;
+
+    /**
+     * Creates a new LightState with the desired color and intensity.
+     *
+     * @param color the desired color and intensity in ARGB format.
+     */
+    public LightState(@ColorInt int color) {
+        mColor = color;
+    }
+
+    private LightState(@NonNull Parcel in) {
+        mColor = in.readInt();
+    }
+
+    /**
+     * Return the color and intensity associated with this LightState.
+     * @return the color and intensity in ARGB format. The A channel is ignored.
+     */
+    public @ColorInt int getColor() {
+        return mColor;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mColor);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Parcelable.Creator<LightState> CREATOR =
+            new Parcelable.Creator<LightState>() {
+                public LightState createFromParcel(Parcel in) {
+                    return new LightState(in);
+                }
+
+                public LightState[] newArray(int size) {
+                    return new LightState[size];
+                }
+            };
+}
diff --git a/core/java/android/hardware/lights/LightsManager.java b/core/java/android/hardware/lights/LightsManager.java
new file mode 100644
index 0000000..1bc051b
--- /dev/null
+++ b/core/java/android/hardware/lights/LightsManager.java
@@ -0,0 +1,204 @@
+/*
+ * 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.lights;
+
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
+import android.util.CloseGuard;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.Reference;
+import java.util.List;
+
+/**
+ * The LightsManager class allows control over device lights.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+@SystemService(Context.LIGHTS_SERVICE)
+public final class LightsManager {
+    private static final String TAG = "LightsManager";
+
+    // These enum values copy the values from {@link com.android.server.lights.LightsManager}
+    // and the light HAL. Since 0-7 are lights reserved for system use, only the microphone light
+    // is available through this API.
+    /** Type for lights that indicate microphone usage */
+    public static final int LIGHT_TYPE_MICROPHONE = 8;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"LIGHT_TYPE_"},
+        value = {
+            LIGHT_TYPE_MICROPHONE,
+        })
+    public @interface LightType {}
+
+    @NonNull private final Context mContext;
+    @NonNull private final ILightsManager mService;
+
+    /**
+     * Creates a LightsManager.
+     *
+     * @hide
+     */
+    public LightsManager(@NonNull Context context) throws ServiceNotFoundException {
+        this(context, ILightsManager.Stub.asInterface(
+            ServiceManager.getServiceOrThrow(Context.LIGHTS_SERVICE)));
+    }
+
+    /**
+     * Creates a LightsManager with a provided service implementation.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public LightsManager(@NonNull Context context, @NonNull ILightsManager service) {
+        mContext = Preconditions.checkNotNull(context);
+        mService = Preconditions.checkNotNull(service);
+    }
+
+    /**
+     * Returns the lights available on the device.
+     *
+     * @return A list of available lights
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    public @NonNull List<Light> getLights() {
+        try {
+            return mService.getLights();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns the state of a specified light.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    @TestApi
+    public @NonNull LightState getLightState(@NonNull Light light) {
+        Preconditions.checkNotNull(light);
+        try {
+            return mService.getLightState(light.getId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Creates a new LightsSession that can be used to control the device lights.
+     */
+    @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+    public @NonNull LightsSession openSession() {
+        try {
+            final LightsSession session = new LightsSession();
+            mService.openSession(session.mToken);
+            return session;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Encapsulates a session that can be used to control device lights and represents the lifetime
+     * of the requests.
+     */
+    public final class LightsSession implements AutoCloseable {
+
+        private final IBinder mToken = new Binder();
+
+        private final CloseGuard mCloseGuard = new CloseGuard();
+        private boolean mClosed = false;
+
+        /**
+         * Instantiated by {@link LightsManager#openSession()}.
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        private LightsSession() {
+            mCloseGuard.open("close");
+        }
+
+        /**
+         * Sends a request to modify the states of multiple lights.
+         *
+         * <p>This method only controls lights that aren't overridden by higher-priority sessions.
+         * Additionally, lights not controlled by this session can be controlled by lower-priority
+         * sessions.
+         *
+         * @param request the settings for lights that should change
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        public void setLights(@NonNull LightsRequest request) {
+            Preconditions.checkNotNull(request);
+            if (!mClosed) {
+                try {
+                    mService.setLightStates(mToken, request.mLightIds, request.mLightStates);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+        }
+
+        /**
+         * Closes the session, reverting all changes made through it.
+         */
+        @RequiresPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS)
+        @Override
+        public void close() {
+            if (!mClosed) {
+                try {
+                    mService.closeSession(mToken);
+                    mClosed = true;
+                    mCloseGuard.close();
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+            }
+            Reference.reachabilityFence(this);
+        }
+
+        /** @hide */
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                mCloseGuard.warnIfOpen();
+                close();
+            } finally {
+                super.finalize();
+            }
+        }
+    }
+}
diff --git a/core/java/android/hardware/lights/LightsRequest.java b/core/java/android/hardware/lights/LightsRequest.java
new file mode 100644
index 0000000..a36da4c
--- /dev/null
+++ b/core/java/android/hardware/lights/LightsRequest.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 android.hardware.lights;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.util.SparseArray;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Encapsulates a request to modify the state of multiple lights.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class LightsRequest {
+
+    /** Visible to {@link LightsManager.Session}. */
+    final int[] mLightIds;
+
+    /** Visible to {@link LightsManager.Session}. */
+    final LightState[] mLightStates;
+
+    /**
+     * Can only be constructed via {@link LightsRequest.Builder#build()}.
+     */
+    private LightsRequest(SparseArray<LightState> changes) {
+        final int n = changes.size();
+        mLightIds = new int[n];
+        mLightStates = new LightState[n];
+        for (int i = 0; i < n; i++) {
+            mLightIds[i] = changes.keyAt(i);
+            mLightStates[i] = changes.valueAt(i);
+        }
+    }
+
+    /**
+     * Builder for creating device light change requests.
+     */
+    public static final class Builder {
+
+        private final SparseArray<LightState> mChanges = new SparseArray<>();
+
+        /**
+         * Overrides the color and intensity of a given light.
+         *
+         * @param light the light to modify
+         * @param state the desired color and intensity of the light
+         */
+        public @NonNull Builder setLight(@NonNull Light light, @NonNull LightState state) {
+            Preconditions.checkNotNull(light);
+            Preconditions.checkNotNull(state);
+            mChanges.put(light.getId(), state);
+            return this;
+        }
+
+        /**
+         * Removes the override for the color and intensity of a given light.
+         *
+         * @param light the light to modify
+         */
+        public @NonNull Builder clearLight(@NonNull Light light) {
+            Preconditions.checkNotNull(light);
+            mChanges.put(light.getId(), null);
+            return this;
+        }
+
+        /**
+         * Create a LightsRequest object used to override lights on the device.
+         *
+         * <p>The generated {@link LightsRequest} should be used in
+         * {@link LightsManager.Session#setLights(LightsLightsRequest).
+         */
+        public @NonNull LightsRequest build() {
+            return new LightsRequest(mChanges);
+        }
+    }
+}
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..1001f80 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -44,7 +44,9 @@
  * 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
  */
@@ -196,7 +198,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 +222,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 +256,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 +286,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 +329,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 +355,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 +393,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 +412,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 +492,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 +524,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 +555,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 +586,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 +616,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 +765,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 +805,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 +827,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 +854,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/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index d43a619..a30fd6b 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -130,7 +130,7 @@
         aidlPhrase.id = apiPhrase.id;
         aidlPhrase.recognitionModes = api2aidlRecognitionModes(apiPhrase.recognitionModes);
         aidlPhrase.users = Arrays.copyOf(apiPhrase.users, apiPhrase.users.length);
-        aidlPhrase.locale = apiPhrase.locale;
+        aidlPhrase.locale = apiPhrase.locale.toLanguageTag();
         aidlPhrase.text = apiPhrase.text;
         return aidlPhrase;
     }
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index eb5d0cb..ef76c62 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -17,6 +17,7 @@
 package android.hardware.soundtrigger;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -24,7 +25,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.service.voice.AlwaysOnHotwordDetector;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -35,6 +35,8 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -66,9 +68,10 @@
             "com.android.intent.action.MANAGE_VOICE_KEYPHRASES";
     /**
      * Intent extra: The intent extra for the specific manage action that needs to be performed.
-     * Possible values are {@link AlwaysOnHotwordDetector#MANAGE_ACTION_ENROLL},
-     * {@link AlwaysOnHotwordDetector#MANAGE_ACTION_RE_ENROLL}
-     * or {@link AlwaysOnHotwordDetector#MANAGE_ACTION_UN_ENROLL}.
+     *
+     * @see #MANAGE_ACTION_ENROLL
+     * @see #MANAGE_ACTION_RE_ENROLL
+     * @see #MANAGE_ACTION_UN_ENROLL
      */
     public static final String EXTRA_VOICE_KEYPHRASE_ACTION =
             "com.android.intent.extra.VOICE_KEYPHRASE_ACTION";
@@ -86,6 +89,31 @@
             "com.android.intent.extra.VOICE_KEYPHRASE_LOCALE";
 
     /**
+     * Keyphrase management actions used with the {@link #EXTRA_VOICE_KEYPHRASE_ACTION} intent extra
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "MANAGE_ACTION_" }, value = {
+            MANAGE_ACTION_ENROLL,
+            MANAGE_ACTION_RE_ENROLL,
+            MANAGE_ACTION_UN_ENROLL
+    })
+    public @interface ManageActions {}
+
+    /**
+     * Indicates desired action to enroll keyphrase model
+     */
+    public static final int MANAGE_ACTION_ENROLL = 0;
+    /**
+     * Indicates desired action to re-enroll keyphrase model
+     */
+    public static final int MANAGE_ACTION_RE_ENROLL = 1;
+    /**
+     * Indicates desired action to un-enroll keyphrase model
+     */
+    public static final int MANAGE_ACTION_UN_ENROLL = 2;
+
+    /**
      * List of available keyphrases.
      */
     final private KeyphraseMetadata[] mKeyphrases;
@@ -294,15 +322,13 @@
      * for the locale.
      *
      * @param action The enrollment related action that this intent is supposed to perform.
-     *        This can be one of {@link AlwaysOnHotwordDetector#MANAGE_ACTION_ENROLL},
-     *        {@link AlwaysOnHotwordDetector#MANAGE_ACTION_RE_ENROLL}
-     *        or {@link AlwaysOnHotwordDetector#MANAGE_ACTION_UN_ENROLL}
      * @param keyphrase The keyphrase that the user needs to be enrolled to.
      * @param locale The locale for which the enrollment needs to be performed.
      * @return An {@link Intent} to manage the keyphrase. This can be null if managing the
      *         given keyphrase/locale combination isn't possible.
      */
-    public Intent getManageKeyphraseIntent(int action, String keyphrase, Locale locale) {
+    public Intent getManageKeyphraseIntent(@ManageActions int action, String keyphrase,
+            Locale locale) {
         if (mKeyphrasePackageMap == null || mKeyphrasePackageMap.isEmpty()) {
             Slog.w(TAG, "No enrollment application exists");
             return null;
diff --git a/core/java/android/service/controls/actions/ControlAction.aidl b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.aidl
similarity index 81%
copy from core/java/android/service/controls/actions/ControlAction.aidl
copy to core/java/android/hardware/soundtrigger/KeyphraseMetadata.aidl
index b012521..7a5e932 100644
--- a/core/java/android/service/controls/actions/ControlAction.aidl
+++ b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.aidl
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
+/**
+ * Copyright (C) 2014 The Android Open 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,6 @@
  * limitations under the License.
  */
 
-package android.service.controls.actions;
+package android.hardware.soundtrigger;
 
-parcelable ControlAction;
\ No newline at end of file
+parcelable KeyphraseMetadata;
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
index ed8c296..15462de 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
@@ -16,8 +16,13 @@
 
 package android.hardware.soundtrigger;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
 import android.util.ArraySet;
 
+import com.android.internal.util.DataClass;
+
 import java.util.Locale;
 
 /**
@@ -25,37 +30,168 @@
  *
  * @hide
  */
-public class KeyphraseMetadata {
+@DataClass(
+        genEqualsHashCode = true,
+        genToString = true,
+        genConstructor = false,
+        genHiddenConstDefs = true)
+public final class KeyphraseMetadata implements Parcelable {
     public final int id;
+    @NonNull
     public final String keyphrase;
+    @NonNull
     public final ArraySet<Locale> supportedLocales;
     public final int recognitionModeFlags;
 
-    public KeyphraseMetadata(int id, String keyphrase, ArraySet<Locale> supportedLocales,
-            int recognitionModeFlags) {
+    public KeyphraseMetadata(int id, @NonNull String keyphrase,
+            @NonNull ArraySet<Locale> supportedLocales, int recognitionModeFlags) {
         this.id = id;
         this.keyphrase = keyphrase;
         this.supportedLocales = supportedLocales;
         this.recognitionModeFlags = recognitionModeFlags;
     }
 
-    @Override
-    public String toString() {
-        return "id=" + id + ", keyphrase=" + keyphrase + ", supported-locales=" + supportedLocales
-                + ", recognition-modes=" + recognitionModeFlags;
-    }
-
     /**
      * @return Indicates if we support the given phrase.
      */
-    public boolean supportsPhrase(String phrase) {
+    public boolean supportsPhrase(@Nullable String phrase) {
         return keyphrase.isEmpty() || keyphrase.equalsIgnoreCase(phrase);
     }
 
     /**
      * @return Indicates if we support the given locale.
      */
-    public boolean supportsLocale(Locale locale) {
+    public boolean supportsLocale(@Nullable Locale locale) {
         return supportedLocales.isEmpty() || supportedLocales.contains(locale);
     }
+
+
+
+
+    // 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/hardware/soundtrigger/KeyphraseMetadata.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "KeyphraseMetadata { " +
+                "id = " + id + ", " +
+                "keyphrase = " + keyphrase + ", " +
+                "supportedLocales = " + supportedLocales + ", " +
+                "recognitionModeFlags = " + recognitionModeFlags +
+        " }";
+    }
+
+    @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(KeyphraseMetadata other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        KeyphraseMetadata that = (KeyphraseMetadata) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && id == that.id
+                && java.util.Objects.equals(keyphrase, that.keyphrase)
+                && java.util.Objects.equals(supportedLocales, that.supportedLocales)
+                && recognitionModeFlags == that.recognitionModeFlags;
+    }
+
+    @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 + id;
+        _hash = 31 * _hash + java.util.Objects.hashCode(keyphrase);
+        _hash = 31 * _hash + java.util.Objects.hashCode(supportedLocales);
+        _hash = 31 * _hash + recognitionModeFlags;
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeInt(id);
+        dest.writeString(keyphrase);
+        dest.writeArraySet(supportedLocales);
+        dest.writeInt(recognitionModeFlags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ KeyphraseMetadata(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        int _id = in.readInt();
+        String _keyphrase = in.readString();
+        ArraySet<Locale> _supportedLocales = (ArraySet) in.readArraySet(null);
+        int _recognitionModeFlags = in.readInt();
+
+        this.id = _id;
+        this.keyphrase = _keyphrase;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, keyphrase);
+        this.supportedLocales = _supportedLocales;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, supportedLocales);
+        this.recognitionModeFlags = _recognitionModeFlags;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<KeyphraseMetadata> CREATOR
+            = new Parcelable.Creator<KeyphraseMetadata>() {
+        @Override
+        public KeyphraseMetadata[] newArray(int size) {
+            return new KeyphraseMetadata[size];
+        }
+
+        @Override
+        public KeyphraseMetadata createFromParcel(@NonNull android.os.Parcel in) {
+            return new KeyphraseMetadata(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1579290593964L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java",
+            inputSignatures = "public final  int id\npublic final @android.annotation.NonNull java.lang.String keyphrase\npublic final @android.annotation.NonNull android.util.ArraySet<java.util.Locale> supportedLocales\npublic final  int recognitionModeFlags\npublic  boolean supportsPhrase(java.lang.String)\npublic  boolean supportsLocale(java.util.Locale)\nclass KeyphraseMetadata extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genConstructor=false, genHiddenConstDefs=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
 }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 1932f46..d505ae5 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -49,6 +49,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.UUID;
 
 /**
@@ -148,6 +149,7 @@
         public final int maxUsers;
 
         /** Supported recognition modes (bit field, RECOGNITION_MODE_VOICE_TRIGGER ...) */
+        @RecognitionModes
         public final int recognitionModes;
 
         /** Supports seamless transition to capture mode after recognition */
@@ -175,9 +177,9 @@
 
         ModuleProperties(int id, @NonNull String implementor, @NonNull String description,
                 @NonNull String uuid, int version, @NonNull String supportedModelArch,
-                int maxSoundModels, int maxKeyphrases, int maxUsers, int recognitionModes,
-                boolean supportsCaptureTransition, int maxBufferMs,
-                boolean supportsConcurrentCapture, int powerConsumptionMw,
+                int maxSoundModels, int maxKeyphrases, int maxUsers,
+                @RecognitionModes int recognitionModes, boolean supportsCaptureTransition,
+                int maxBufferMs, boolean supportsConcurrentCapture, int powerConsumptionMw,
                 boolean returnsTriggerInEvent, int audioCapabilities) {
             this.id = id;
             this.implementor = requireNonNull(implementor);
@@ -271,16 +273,27 @@
         }
     }
 
-    /*****************************************************************************
+    /**
      * A SoundModel describes the attributes and contains the binary data used by the hardware
      * implementation to detect a particular sound pattern.
      * A specialized version {@link KeyphraseSoundModel} is defined for key phrase
      * sound models.
-     *
-     * @hide
-     ****************************************************************************/
+     */
     public static class SoundModel {
-        /** Undefined sound model type */
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({
+                TYPE_GENERIC_SOUND,
+                TYPE_KEYPHRASE,
+                TYPE_UNKNOWN,
+        })
+        public @interface SoundModelType {}
+
+        /**
+         * Undefined sound model type
+         * @hide
+         */
         public static final int TYPE_UNKNOWN = -1;
 
         /** Keyphrase sound model */
@@ -293,15 +306,14 @@
         public static final int TYPE_GENERIC_SOUND = 1;
 
         /** Unique sound model identifier */
-        @UnsupportedAppUsage
         @NonNull
         public final UUID uuid;
 
         /** Sound model type (e.g. TYPE_KEYPHRASE); */
+        @SoundModelType
         public final int type;
 
         /** Unique sound model vendor identifier */
-        @UnsupportedAppUsage
         @NonNull
         public final UUID vendorUuid;
 
@@ -309,11 +321,11 @@
         public final int version;
 
         /** Opaque data. For use by vendor implementation and enrollment application */
-        @UnsupportedAppUsage
         @NonNull
         public final byte[] data;
 
-        public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, int type,
+        /** @hide */
+        public SoundModel(@NonNull UUID uuid, @Nullable UUID vendorUuid, @SoundModelType int type,
                 @Nullable byte[] data, int version) {
             this.uuid = requireNonNull(uuid);
             this.vendorUuid = vendorUuid != null ? vendorUuid : new UUID(0, 0);
@@ -336,67 +348,90 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (this == obj)
+            if (this == obj) {
                 return true;
-            if (obj == null)
+            }
+            if (obj == null) {
                 return false;
-            if (!(obj instanceof SoundModel))
+            }
+            if (!(obj instanceof SoundModel)) {
                 return false;
+            }
             SoundModel other = (SoundModel) obj;
-            if (type != other.type)
+            if (type != other.type) {
                 return false;
+            }
             if (uuid == null) {
-                if (other.uuid != null)
+                if (other.uuid != null) {
                     return false;
-            } else if (!uuid.equals(other.uuid))
+                }
+            } else if (!uuid.equals(other.uuid)) {
                 return false;
+            }
             if (vendorUuid == null) {
-                if (other.vendorUuid != null)
+                if (other.vendorUuid != null) {
                     return false;
-            } else if (!vendorUuid.equals(other.vendorUuid))
+                }
+            } else if (!vendorUuid.equals(other.vendorUuid)) {
                 return false;
-            if (!Arrays.equals(data, other.data))
+            }
+            if (!Arrays.equals(data, other.data)) {
                 return false;
-            if (version != other.version)
+            }
+            if (version != other.version) {
                 return false;
+            }
             return true;
         }
     }
 
-    /*****************************************************************************
+    /**
      * A Keyphrase describes a key phrase that can be detected by a
      * {@link KeyphraseSoundModel}
-     *
-     * @hide
-     ****************************************************************************/
-    public static class Keyphrase implements Parcelable {
+     */
+    public static final class Keyphrase implements Parcelable {
         /** Unique identifier for this keyphrase */
-        @UnsupportedAppUsage
         public final int id;
 
-        /** Recognition modes supported for this key phrase in the model */
-        @UnsupportedAppUsage
+        /**
+         * Recognition modes supported for this key phrase in the model
+         *
+         * @see #RECOGNITION_MODE_VOICE_TRIGGER
+         * @see #RECOGNITION_MODE_USER_IDENTIFICATION
+         * @see #RECOGNITION_MODE_USER_AUTHENTICATION
+         * @see #RECOGNITION_MODE_GENERIC
+         */
+        @RecognitionModes
         public final int recognitionModes;
 
-        /** Locale of the keyphrase. JAVA Locale string e.g en_US */
-        @UnsupportedAppUsage
+        /** Locale of the keyphrase. */
         @NonNull
-        public final String locale;
+        public final Locale locale;
 
         /** Key phrase text */
-        @UnsupportedAppUsage
         @NonNull
         public final String text;
 
-        /** Users this key phrase has been trained for. countains sound trigger specific user IDs
-         * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}. */
-        @UnsupportedAppUsage
+        /**
+         * Users this key phrase has been trained for. countains sound trigger specific user IDs
+         * derived from system user IDs {@link android.os.UserHandle#getIdentifier()}.
+         */
         @NonNull
         public final int[] users;
 
-        @UnsupportedAppUsage
-        public Keyphrase(int id, int recognitionModes, @NonNull String locale, @NonNull String text,
-                @Nullable int[] users) {
+        /**
+         * Constructor for Keyphrase describes a key phrase that can be detected by a
+         * {@link KeyphraseSoundModel}
+         *
+         * @param id Unique keyphrase identifier for this keyphrase
+         * @param recognitionModes Bit field representation of recognition modes this keyphrase
+         *                         supports
+         * @param locale Locale of the keyphrase
+         * @param text Key phrase text
+         * @param users Users this key phrase has been trained for.
+         */
+        public Keyphrase(int id, @RecognitionModes int recognitionModes, @NonNull Locale locale,
+                @NonNull String text, @Nullable int[] users) {
             this.id = id;
             this.recognitionModes = recognitionModes;
             this.locale = requireNonNull(locale);
@@ -404,21 +439,27 @@
             this.users = users != null ? users : new int[0];
         }
 
-        public static final @android.annotation.NonNull Parcelable.Creator<Keyphrase> CREATOR
-                = new Parcelable.Creator<Keyphrase>() {
-            public Keyphrase createFromParcel(Parcel in) {
-                return Keyphrase.fromParcel(in);
+        public static final @NonNull Parcelable.Creator<Keyphrase> CREATOR =
+                new Parcelable.Creator<Keyphrase>() {
+            @NonNull
+            public Keyphrase createFromParcel(@NonNull Parcel in) {
+                return Keyphrase.readFromParcel(in);
             }
 
+            @NonNull
             public Keyphrase[] newArray(int size) {
                 return new Keyphrase[size];
             }
         };
 
-        private static Keyphrase fromParcel(Parcel in) {
+        /**
+         * Read from Parcel to generate keyphrase
+         */
+        @NonNull
+        public static Keyphrase readFromParcel(@NonNull Parcel in) {
             int id = in.readInt();
             int recognitionModes = in.readInt();
-            String locale = in.readString();
+            Locale locale = Locale.forLanguageTag(in.readString());
             String text = in.readString();
             int[] users = null;
             int numUsers = in.readInt();
@@ -430,10 +471,10 @@
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeInt(id);
             dest.writeInt(recognitionModes);
-            dest.writeString(locale);
+            dest.writeString(locale.toLanguageTag());
             dest.writeString(text);
             if (users != null) {
                 dest.writeInt(users.length);
@@ -443,6 +484,7 @@
             }
         }
 
+        /** @hide */
         @Override
         public int describeContents() {
             return 0;
@@ -462,49 +504,57 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (this == obj)
+            if (this == obj) {
                 return true;
-            if (obj == null)
+            }
+            if (obj == null) {
                 return false;
-            if (getClass() != obj.getClass())
+            }
+            if (getClass() != obj.getClass()) {
                 return false;
+            }
             Keyphrase other = (Keyphrase) obj;
             if (text == null) {
-                if (other.text != null)
+                if (other.text != null) {
                     return false;
-            } else if (!text.equals(other.text))
+                }
+            } else if (!text.equals(other.text)) {
                 return false;
-            if (id != other.id)
+            }
+            if (id != other.id) {
                 return false;
+            }
             if (locale == null) {
-                if (other.locale != null)
+                if (other.locale != null) {
                     return false;
-            } else if (!locale.equals(other.locale))
+                }
+            } else if (!locale.equals(other.locale)) {
                 return false;
-            if (recognitionModes != other.recognitionModes)
+            }
+            if (recognitionModes != other.recognitionModes) {
                 return false;
-            if (!Arrays.equals(users, other.users))
+            }
+            if (!Arrays.equals(users, other.users)) {
                 return false;
+            }
             return true;
         }
 
         @Override
         public String toString() {
-            return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes + ", locale="
-                    + locale + ", text=" + text + ", users=" + Arrays.toString(users) + "]";
+            return "Keyphrase [id=" + id + ", recognitionModes=" + recognitionModes
+                    + ", locale=" + locale.toLanguageTag() + ", text=" + text
+                    + ", users=" + Arrays.toString(users) + "]";
         }
     }
 
-    /*****************************************************************************
+    /**
      * A KeyphraseSoundModel is a specialized {@link SoundModel} for key phrases.
      * It contains data needed by the hardware to detect a certain number of key phrases
      * and the list of corresponding {@link Keyphrase} descriptors.
-     *
-     * @hide
-     ****************************************************************************/
-    public static class KeyphraseSoundModel extends SoundModel implements Parcelable {
+     */
+    public static final class KeyphraseSoundModel extends SoundModel implements Parcelable {
         /** Key phrases in this sound model */
-        @UnsupportedAppUsage
         @NonNull
         public final Keyphrase[] keyphrases; // keyword phrases in model
 
@@ -515,24 +565,29 @@
             this.keyphrases = keyphrases != null ? keyphrases : new Keyphrase[0];
         }
 
-        @UnsupportedAppUsage
         public KeyphraseSoundModel(@NonNull UUID uuid, @NonNull UUID vendorUuid,
                 @Nullable byte[] data, @Nullable Keyphrase[] keyphrases) {
             this(uuid, vendorUuid, data, keyphrases, -1);
         }
 
-        public static final @android.annotation.NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR
-                = new Parcelable.Creator<KeyphraseSoundModel>() {
-            public KeyphraseSoundModel createFromParcel(Parcel in) {
-                return KeyphraseSoundModel.fromParcel(in);
+        public static final @NonNull Parcelable.Creator<KeyphraseSoundModel> CREATOR =
+                new Parcelable.Creator<KeyphraseSoundModel>() {
+            @NonNull
+            public KeyphraseSoundModel createFromParcel(@NonNull Parcel in) {
+                return KeyphraseSoundModel.readFromParcel(in);
             }
 
+            @NonNull
             public KeyphraseSoundModel[] newArray(int size) {
                 return new KeyphraseSoundModel[size];
             }
         };
 
-        private static KeyphraseSoundModel fromParcel(Parcel in) {
+        /**
+         * Read from Parcel to generate KeyphraseSoundModel
+         */
+        @NonNull
+        public static KeyphraseSoundModel readFromParcel(@NonNull Parcel in) {
             UUID uuid = UUID.fromString(in.readString());
             UUID vendorUuid = null;
             int length = in.readInt();
@@ -545,13 +600,14 @@
             return new KeyphraseSoundModel(uuid, vendorUuid, data, keyphrases, version);
         }
 
+        /** @hide */
         @Override
         public int describeContents() {
             return 0;
         }
 
         @Override
-        public void writeToParcel(Parcel dest, int flags) {
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeString(uuid.toString());
             if (vendorUuid == null) {
                 dest.writeInt(-1);
@@ -583,15 +639,19 @@
 
         @Override
         public boolean equals(Object obj) {
-            if (this == obj)
+            if (this == obj) {
                 return true;
-            if (!super.equals(obj))
+            }
+            if (!super.equals(obj)) {
                 return false;
-            if (!(obj instanceof KeyphraseSoundModel))
+            }
+            if (!(obj instanceof KeyphraseSoundModel)) {
                 return false;
+            }
             KeyphraseSoundModel other = (KeyphraseSoundModel) obj;
-            if (!Arrays.equals(keyphrases, other.keyphrases))
+            if (!Arrays.equals(keyphrases, other.keyphrases)) {
                 return false;
+            }
             return true;
         }
     }
@@ -760,31 +820,32 @@
     }
 
     /**
-     *  Modes for key phrase recognition
+     * Modes for key phrase recognition
+     * @hide
      */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "RECOGNITION_MODE_" }, value = {
+            RECOGNITION_MODE_VOICE_TRIGGER,
+            RECOGNITION_MODE_USER_IDENTIFICATION,
+            RECOGNITION_MODE_USER_AUTHENTICATION,
+            RECOGNITION_MODE_GENERIC
+    })
+    public @interface RecognitionModes {}
 
     /**
-     * Simple recognition of the key phrase
-     *
-     * @hide
+     * Trigger on recognition of a key phrase
      */
     public static final int RECOGNITION_MODE_VOICE_TRIGGER = 0x1;
     /**
      * Trigger only if one user is identified
-     *
-     * @hide
      */
     public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 0x2;
     /**
      * Trigger only if one user is authenticated
-     *
-     * @hide
      */
     public static final int RECOGNITION_MODE_USER_AUTHENTICATION = 0x4;
     /**
      * Generic (non-speech) recognition.
-     *
-     * @hide
      */
     public static final int RECOGNITION_MODE_GENERIC = 0x8;
 
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/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 81a0d62..92047dc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -20,8 +20,8 @@
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
+import static android.view.WindowInsets.Type.navigationBars;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
@@ -1240,16 +1240,16 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
                 WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
-        mWindow.getWindow().setFitWindowInsetsTypes(WindowInsets.Type.systemBars());
-        mWindow.getWindow().addPrivateFlags(PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND);
+        mWindow.getWindow().getAttributes().setFitInsetsTypes(WindowInsets.Type.statusBars());
+
+        // IME layout should always be inset by navigation bar, no matter it's current visibility.
         mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
                 (v, insets) -> v.onApplyWindowInsets(
-                        new WindowInsets.Builder(insets).setSystemWindowInsets(
-                                android.graphics.Insets.of(
-                                        insets.getSystemWindowInsetLeft(),
-                                        insets.getSystemWindowInsetTop(),
-                                        insets.getSystemWindowInsetRight(),
-                                        insets.getStableInsetBottom())).build()));
+                        new WindowInsets.Builder(insets).setInsets(
+                                navigationBars(),
+                                insets.getInsetsIgnoringVisibility(navigationBars()))
+                                .build()));
+
         // For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
         // by default (but IME developers can opt this out later if they want a new behavior).
         mWindow.getWindow().setFlags(
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl b/core/java/android/net/ConnectivityDiagnosticsManager.aidl
similarity index 73%
copy from telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
copy to core/java/android/net/ConnectivityDiagnosticsManager.aidl
index e9cbd9c..82ba0ca 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.aidl
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.aidl
@@ -1,6 +1,6 @@
-/*
+/**
  *
- * 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 +15,7 @@
  * limitations under the License.
  */
 
-package android.telephony.ims;
+package android.net;
 
-parcelable RcsMessageQueryParams;
+parcelable ConnectivityDiagnosticsManager.ConnectivityReport;
+parcelable ConnectivityDiagnosticsManager.DataStallReport;
\ No newline at end of file
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 6afdb5e..b13e4b7 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -18,10 +18,20 @@
 
 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;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -47,38 +57,169 @@
  * </ul>
  */
 public class ConnectivityDiagnosticsManager {
-    public static final int DETECTION_METHOD_DNS_EVENTS = 1;
-    public static final int DETECTION_METHOD_TCP_METRICS = 2;
+    private final Context mContext;
+    private final IConnectivityManager mService;
 
     /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(
-            prefix = {"DETECTION_METHOD_"},
-            value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
-    public @interface DetectionMethod {}
+    public ConnectivityDiagnosticsManager(Context context, IConnectivityManager service) {
+        mContext = Preconditions.checkNotNull(context, "missing context");
+        mService = Preconditions.checkNotNull(service, "missing IConnectivityManager");
+    }
 
     /** @hide */
-    public ConnectivityDiagnosticsManager() {}
+    @VisibleForTesting
+    public static boolean persistableBundleEquals(
+            @Nullable PersistableBundle a, @Nullable PersistableBundle b) {
+        if (a == b) return true;
+        if (a == null || b == null) return false;
+        if (!Objects.equals(a.keySet(), b.keySet())) return false;
+        for (String key : a.keySet()) {
+            if (!Objects.equals(a.get(key), b.get(key))) return false;
+        }
+        return true;
+    }
 
     /** Class that includes connectivity information for a specific Network at a specific time. */
-    public static class ConnectivityReport {
+    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 public final Network network;
+        @NonNull private final Network mNetwork;
 
         /**
          * The timestamp for the report. The timestamp is taken from {@link
          * System#currentTimeMillis}.
          */
-        public final long reportTimestamp;
+        private final long mReportTimestamp;
 
         /** LinkProperties available on the Network at the reported timestamp */
-        @NonNull public final LinkProperties linkProperties;
+        @NonNull private final LinkProperties mLinkProperties;
 
         /** NetworkCapabilities available on the Network at the reported timestamp */
-        @NonNull public final NetworkCapabilities networkCapabilities;
+        @NonNull private final NetworkCapabilities mNetworkCapabilities;
 
         /** PersistableBundle that may contain additional info about the report */
-        @NonNull public final PersistableBundle additionalInfo;
+        @NonNull private final PersistableBundle mAdditionalInfo;
 
         /**
          * Constructor for ConnectivityReport.
@@ -101,30 +242,191 @@
                 @NonNull LinkProperties linkProperties,
                 @NonNull NetworkCapabilities networkCapabilities,
                 @NonNull PersistableBundle additionalInfo) {
-            this.network = network;
-            this.reportTimestamp = reportTimestamp;
-            this.linkProperties = linkProperties;
-            this.networkCapabilities = networkCapabilities;
-            this.additionalInfo = additionalInfo;
+            mNetwork = network;
+            mReportTimestamp = reportTimestamp;
+            mLinkProperties = linkProperties;
+            mNetworkCapabilities = networkCapabilities;
+            mAdditionalInfo = additionalInfo;
         }
+
+        /**
+         * Returns the Network for this ConnectivityReport.
+         *
+         * @return The Network for which this ConnectivityReport applied
+         */
+        @NonNull
+        public Network getNetwork() {
+            return mNetwork;
+        }
+
+        /**
+         * Returns the epoch timestamp (milliseconds) for when this report was taken.
+         *
+         * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}.
+         */
+        public long getReportTimestamp() {
+            return mReportTimestamp;
+        }
+
+        /**
+         * Returns the LinkProperties available when this report was taken.
+         *
+         * @return LinkProperties available on the Network at the reported timestamp
+         */
+        @NonNull
+        public LinkProperties getLinkProperties() {
+            return new LinkProperties(mLinkProperties);
+        }
+
+        /**
+         * Returns the NetworkCapabilities when this report was taken.
+         *
+         * @return NetworkCapabilities available on the Network at the reported timestamp
+         */
+        @NonNull
+        public NetworkCapabilities getNetworkCapabilities() {
+            return new NetworkCapabilities(mNetworkCapabilities);
+        }
+
+        /**
+         * Returns a PersistableBundle with additional info for this report.
+         *
+         * @return PersistableBundle that may contain additional info about the report
+         */
+        @NonNull
+        public PersistableBundle getAdditionalInfo() {
+            return new PersistableBundle(mAdditionalInfo);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (this == o) return true;
+            if (!(o instanceof ConnectivityReport)) return false;
+            final ConnectivityReport that = (ConnectivityReport) o;
+
+            // PersistableBundle is optimized to avoid unparcelling data unless fields are
+            // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over
+            // {@link PersistableBundle#kindofEquals}.
+            return mReportTimestamp == that.mReportTimestamp
+                    && mNetwork.equals(that.mNetwork)
+                    && mLinkProperties.equals(that.mLinkProperties)
+                    && mNetworkCapabilities.equals(that.mNetworkCapabilities)
+                    && persistableBundleEquals(mAdditionalInfo, that.mAdditionalInfo);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(
+                    mNetwork,
+                    mReportTimestamp,
+                    mLinkProperties,
+                    mNetworkCapabilities,
+                    mAdditionalInfo);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeParcelable(mNetwork, flags);
+            dest.writeLong(mReportTimestamp);
+            dest.writeParcelable(mLinkProperties, flags);
+            dest.writeParcelable(mNetworkCapabilities, flags);
+            dest.writeParcelable(mAdditionalInfo, flags);
+        }
+
+        /** Implement the Parcelable interface */
+        public static final @NonNull Creator<ConnectivityReport> CREATOR =
+                new Creator<ConnectivityReport>() {
+                    public ConnectivityReport createFromParcel(Parcel in) {
+                        return new ConnectivityReport(
+                                in.readParcelable(null),
+                                in.readLong(),
+                                in.readParcelable(null),
+                                in.readParcelable(null),
+                                in.readParcelable(null));
+                    }
+
+                    public ConnectivityReport[] newArray(int size) {
+                        return new ConnectivityReport[size];
+                    }
+                };
     }
 
     /** Class that includes information for a suspected data stall on a specific Network */
-    public static class DataStallReport {
+    public static final class DataStallReport implements Parcelable {
+        public static final int DETECTION_METHOD_DNS_EVENTS = 1;
+        public static final int DETECTION_METHOD_TCP_METRICS = 2;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef(
+                prefix = {"DETECTION_METHOD_"},
+                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 public final Network network;
+        @NonNull private final Network mNetwork;
 
         /**
          * The timestamp for the report. The timestamp is taken from {@link
          * System#currentTimeMillis}.
          */
-        public final long reportTimestamp;
+        private long mReportTimestamp;
 
         /** The detection method used to identify the suspected data stall */
-        @DetectionMethod public final int detectionMethod;
+        @DetectionMethod private final int mDetectionMethod;
 
         /** PersistableBundle that may contain additional information on the suspected data stall */
-        @NonNull public final PersistableBundle stallDetails;
+        @NonNull private final PersistableBundle mStallDetails;
 
         /**
          * Constructor for DataStallReport.
@@ -143,10 +445,150 @@
                 long reportTimestamp,
                 @DetectionMethod int detectionMethod,
                 @NonNull PersistableBundle stallDetails) {
-            this.network = network;
-            this.reportTimestamp = reportTimestamp;
-            this.detectionMethod = detectionMethod;
-            this.stallDetails = stallDetails;
+            mNetwork = network;
+            mReportTimestamp = reportTimestamp;
+            mDetectionMethod = detectionMethod;
+            mStallDetails = stallDetails;
+        }
+
+        /**
+         * Returns the Network for this DataStallReport.
+         *
+         * @return The Network for which this DataStallReport applied
+         */
+        @NonNull
+        public Network getNetwork() {
+            return mNetwork;
+        }
+
+        /**
+         * Returns the epoch timestamp (milliseconds) for when this report was taken.
+         *
+         * @return The timestamp for the report. Taken from {@link System#currentTimeMillis}.
+         */
+        public long getReportTimestamp() {
+            return mReportTimestamp;
+        }
+
+        /**
+         * Returns the detection method used to identify this suspected data stall.
+         *
+         * @return The detection method used to identify the suspected data stall
+         */
+        public int getDetectionMethod() {
+            return mDetectionMethod;
+        }
+
+        /**
+         * 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
+         */
+        @NonNull
+        public PersistableBundle getStallDetails() {
+            return new PersistableBundle(mStallDetails);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (this == o) return true;
+            if (!(o instanceof DataStallReport)) return false;
+            final DataStallReport that = (DataStallReport) o;
+
+            // PersistableBundle is optimized to avoid unparcelling data unless fields are
+            // referenced. Because of this, use {@link ConnectivityDiagnosticsManager#equals} over
+            // {@link PersistableBundle#kindofEquals}.
+            return mReportTimestamp == that.mReportTimestamp
+                    && mDetectionMethod == that.mDetectionMethod
+                    && mNetwork.equals(that.mNetwork)
+                    && persistableBundleEquals(mStallDetails, that.mStallDetails);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mNetwork, mReportTimestamp, mDetectionMethod, mStallDetails);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeParcelable(mNetwork, flags);
+            dest.writeLong(mReportTimestamp);
+            dest.writeInt(mDetectionMethod);
+            dest.writeParcelable(mStallDetails, flags);
+        }
+
+        /** Implement the Parcelable interface */
+        public static final @NonNull Creator<DataStallReport> CREATOR =
+                new Creator<DataStallReport>() {
+                    public DataStallReport createFromParcel(Parcel in) {
+                        return new DataStallReport(
+                                in.readParcelable(null),
+                                in.readLong(),
+                                in.readInt(),
+                                in.readParcelable(null));
+                    }
+
+                    public DataStallReport[] newArray(int size) {
+                        return new DataStallReport[size];
+                    }
+                };
+    }
+
+    /** @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);
+                });
+            });
         }
     }
 
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/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/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/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 7cc78f7..7cc569a 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -304,7 +304,10 @@
     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
         // The subtype can be changed with (TODO) setLegacySubtype, but it starts
         // with the type and an empty description.
-        return new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, "");
+        final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacyType,
+                config.legacyTypeName, "");
+        ni.setIsAvailable(true);
+        return ni;
     }
 
     /**
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 47c08a4..5cd4eb5 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -73,14 +73,13 @@
     /**
      * Constructs a new NetworkKey for the given wifi {@link ScanResult}.
      *
-     * @return  A new {@link NetworkKey} instance or <code>null</code> if the given
-     *          {@link ScanResult} instance is malformed.
+     * @return A new {@link NetworkKey} instance or <code>null</code> if the given
+     *         {@link ScanResult} instance is malformed.
+     * @throws NullPointerException
      */
     @Nullable
-    public static NetworkKey createFromScanResult(@Nullable ScanResult result) {
-        if (result == null) {
-            return null;
-        }
+    public static NetworkKey createFromScanResult(@NonNull ScanResult result) {
+        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/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index c233ec0..a190c47 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -35,6 +35,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -385,7 +386,6 @@
      *
      * @hide
      */
-    @SystemApi
     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
         try {
@@ -396,6 +396,28 @@
     }
 
     /**
+     * Request scoring for networks.
+     *
+     * <p>
+     * Note: The results (i.e scores) for these networks, when available will be provided via the
+     * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
+     * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
+     * receive the results before requesting new scores via this API.
+     *
+     * @return true if the request was successfully sent, or false if there is no active scorer.
+     * @throws SecurityException if the caller does not hold the
+     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
+    public boolean requestScores(@NonNull Collection<NetworkKey> networks)
+            throws SecurityException {
+        return requestScores(networks.toArray(new NetworkKey[0]));
+    }
+
+    /**
      * Register a network score cache.
      *
      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
@@ -454,26 +476,25 @@
 
     /**
      * Base class for network score cache callback. Should be extended by applications and set
-     * when calling {@link #registerNetworkScoreCallback(int, int, NetworkScoreCallback,
-     * Executor)}
+     * when calling {@link #registerNetworkScoreCallback(int, int, Executor, NetworkScoreCallback)}.
      *
      * @hide
      */
     @SystemApi
-    public interface NetworkScoreCallback {
+    public abstract static class NetworkScoreCallback {
         /**
          * Called when a new set of network scores are available.
          * This is triggered in response when the client invokes
-         * {@link #requestScores(NetworkKey[])} to score a new set of networks.
+         * {@link #requestScores(Collection)} to score a new set of networks.
          *
          * @param networks List of {@link ScoredNetwork} containing updated scores.
          */
-        void updateScores(@NonNull List<ScoredNetwork> networks);
+        public abstract void onScoresUpdated(@NonNull Collection<ScoredNetwork> networks);
 
         /**
          * Invokes when all the previously provided scores are no longer valid.
          */
-        void clearScores();
+        public abstract void onScoresInvalidated();
     }
 
     /**
@@ -492,7 +513,7 @@
         public void updateScores(@NonNull List<ScoredNetwork> networks) {
             Binder.clearCallingIdentity();
             mExecutor.execute(() -> {
-                mCallback.updateScores(networks);
+                mCallback.onScoresUpdated(networks);
             });
         }
 
@@ -500,7 +521,7 @@
         public void clearScores() {
             Binder.clearCallingIdentity();
             mExecutor.execute(() -> {
-                mCallback.clearScores();
+                mCallback.onScoresInvalidated();
             });
         }
     }
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/StringNetworkSpecifier.java b/core/java/android/net/StringNetworkSpecifier.java
index 83dbc63..6ae5971 100644
--- a/core/java/android/net/StringNetworkSpecifier.java
+++ b/core/java/android/net/StringNetworkSpecifier.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import android.annotation.NonNull;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -27,7 +26,6 @@
 import java.util.Objects;
 
 /** @hide */
-@SystemApi
 public final class StringNetworkSpecifier extends NetworkSpecifier implements Parcelable {
     /**
      * Arbitrary string used to pass (additional) information to the network factory.
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..152141e 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -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/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/TelephonyServiceManager.java b/core/java/android/os/TelephonyServiceManager.java
index 4f5f3d6..c67dedb 100644
--- a/core/java/android/os/TelephonyServiceManager.java
+++ b/core/java/android/os/TelephonyServiceManager.java
@@ -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/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/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/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 84ceca0..091d78e 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -796,6 +796,14 @@
     }
 
     /**
+     * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION;
+     * @hide
+     */
+    public static @NonNull List<String> getPublicNamespaces() {
+        return PUBLIC_NAMESPACES;
+    }
+
+    /**
      * Interface for monitoring changes to properties. Implementations will receive callbacks when
      * properties change, including a {@link Properties} object which contains a single namespace
      * and all of the properties which changed for that namespace. This includes properties which
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c7c3140..a624120 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -63,6 +63,7 @@
 import android.os.LocaleList;
 import android.os.PowerManager.AutoPowerSaveModeTriggers;
 import android.os.Process;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -2161,6 +2162,11 @@
     public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
 
     /**
+     * @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests
+     */
+    public static final String CALL_METHOD_MONITOR_CALLBACK_KEY = "_monitor_callback_key";
+
+    /**
      * @hide - String argument extra to the fast-path call()-based requests
      */
     public static final String CALL_METHOD_FLAGS_KEY = "_flags";
@@ -2218,6 +2224,26 @@
     /** @hide - Private call() method to reset to defaults the 'configuration' table */
     public static final String CALL_METHOD_LIST_CONFIG = "LIST_config";
 
+    /** @hide - Private call() method to register monitor callback for 'configuration' table */
+    public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
+            "REGISTER_MONITOR_CALLBACK_config";
+
+    /** @hide - String argument extra to the config monitor callback */
+    public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type";
+
+    /** @hide - String argument extra to the config monitor callback */
+    public static final String EXTRA_ACCESS_CALLBACK = "access_callback";
+
+    /** @hide - String argument extra to the config monitor callback */
+    public static final String EXTRA_NAMESPACE_UPDATED_CALLBACK =
+            "namespace_updated_callback";
+
+    /** @hide - String argument extra to the config monitor callback */
+    public static final String EXTRA_NAMESPACE = "namespace";
+
+    /** @hide - String argument extra to the config monitor callback */
+    public static final String EXTRA_CALLING_PACKAGE = "calling_package";
+
     /**
      * Activity Extra: Limit available options in launched activity based on the given authority.
      * <p>
@@ -8376,6 +8402,7 @@
          *
          * @hide
          */
+        @SystemApi
         public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
 
         /**
@@ -9335,6 +9362,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.
         */
@@ -9710,6 +9747,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.
@@ -11055,6 +11101,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
          */
@@ -14155,6 +14210,37 @@
             }
         }
 
+        /**
+         * Register callback for monitoring Config table.
+         *
+         * @param resolver Handle to the content resolver.
+         * @param callback callback to register
+         *
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS)
+        public static void registerMonitorCallback(@NonNull ContentResolver resolver,
+                @NonNull RemoteCallback callback) {
+            registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback);
+        }
+
+        private static void registerMonitorCallbackAsUser(
+                @NonNull ContentResolver resolver, @UserIdInt int userHandle,
+                @NonNull RemoteCallback callback) {
+            try {
+                Bundle arg = new Bundle();
+                arg.putInt(CALL_METHOD_USER_KEY, userHandle);
+                arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback);
+                IContentProvider cp = sProviderHolder.getProvider(resolver);
+                cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+                        sProviderHolder.mUri.getAuthority(),
+                        CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Can't register config monitor callback", e);
+            }
+        }
+
         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 4fa7c42..9da584e 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;
@@ -4565,32 +4564,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},
@@ -4602,53 +4575,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
@@ -4659,125 +4585,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";
     }
 
     /**
@@ -5305,6 +5117,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/ConfirmationPrompt.java b/core/java/android/security/ConfirmationPrompt.java
index 5330cff..f67af85 100644
--- a/core/java/android/security/ConfirmationPrompt.java
+++ b/core/java/android/security/ConfirmationPrompt.java
@@ -212,20 +212,16 @@
 
     private int getUiOptionsAsFlags() {
         int uiOptionsAsFlags = 0;
-        try {
-            ContentResolver contentResolver = mContext.getContentResolver();
-            int inversionEnabled = Settings.Secure.getInt(contentResolver,
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
-            if (inversionEnabled == 1) {
-                uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_INVERTED_FLAG;
-            }
-            float fontScale = Settings.System.getFloat(contentResolver,
-                    Settings.System.FONT_SCALE);
-            if (fontScale > 1.0) {
-                uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG;
-            }
-        } catch (SettingNotFoundException e) {
-            Log.w(TAG, "Unexpected SettingNotFoundException");
+        ContentResolver contentResolver = mContext.getContentResolver();
+        int inversionEnabled = Settings.Secure.getInt(contentResolver,
+                Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0);
+        if (inversionEnabled == 1) {
+            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_INVERTED_FLAG;
+        }
+        float fontScale = Settings.System.getFloat(contentResolver,
+                Settings.System.FONT_SCALE, (float) 1.0);
+        if (fontScale > 1.0) {
+            uiOptionsAsFlags |= UI_OPTION_ACCESSIBILITY_MAGNIFIED_FLAG;
         }
         return uiOptionsAsFlags;
     }
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index dc0f562..9333dbd 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();
     }
 
@@ -717,6 +749,7 @@
         parcel.writeInt(mFlags);
         parcel.writeIntArray(mCancelIds);
         parcel.writeInt(mRequestId);
+        parcel.writeParcelable(mInlineActions, flags);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<FillResponse> CREATOR =
@@ -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/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/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 3d82946..36e2d1f 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,37 @@
         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);
+
+                DataShareReadAdapterDelegate delegate =
+                        new DataShareReadAdapterDelegate(executor, adapter);
+
+                try {
+                    callback.accept(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 +649,57 @@
             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;
+
+        DataShareReadAdapterDelegate(Executor executor, DataShareReadAdapter adapter) {
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(adapter);
+
+            mExecutorReference = new WeakReference<>(executor);
+            mAdapterReference = new WeakReference<>(adapter);
+        }
+
+        @Override
+        public void start(ParcelFileDescriptor fd, ICancellationSignal remoteCancellationSignal)
+                throws RemoteException {
+            synchronized (mLock) {
+                CancellationSignal cancellationSignal = new CancellationSignal();
+                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..d9350ba
--- /dev/null
+++ b/core/java/android/service/contentcapture/DataShareReadAdapter.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.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 (e.g. due to a
+     * timeout).
+     **/
+    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 68%
rename from core/java/android/os/StatsLogEventWrapper.aidl
rename to core/java/android/service/contentcapture/IDataShareCallback.aidl
index 766343e..c1aa1bb 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,12 @@
  * limitations under the License.
  */
 
-package android.os;
+package android.service.contentcapture;
+
+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 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/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.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/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 0f33998..1966f17 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -29,7 +29,6 @@
 import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
-import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.media.AudioFormat;
@@ -67,7 +66,12 @@
     /**
      * Indicates that recognition for the given keyphrase is not supported.
      * No further interaction should be performed with the detector that returns this availability.
+     *
+     * @deprecated This is no longer a valid state. Enrollment can occur outside of
+     * {@link KeyphraseEnrollmentInfo} through another privileged application. We can no longer
+     * determine ahead of time if the keyphrase and locale are unsupported by the system.
      */
+    @Deprecated
     public static final int STATE_KEYPHRASE_UNSUPPORTED = -1;
     /**
      * Indicates that the given keyphrase is not enrolled.
@@ -85,34 +89,6 @@
      */
     private static final int STATE_NOT_READY = 0;
 
-    // Keyphrase management actions. Used in getManageIntent() ----//
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "MANAGE_ACTION_" }, value = {
-            MANAGE_ACTION_ENROLL,
-            MANAGE_ACTION_RE_ENROLL,
-            MANAGE_ACTION_UN_ENROLL
-    })
-    private @interface ManageActions {}
-
-    /**
-     * Indicates that we need to enroll.
-     *
-     * @hide
-     */
-    public static final int MANAGE_ACTION_ENROLL = 0;
-    /**
-     * Indicates that we need to re-enroll.
-     *
-     * @hide
-     */
-    public static final int MANAGE_ACTION_RE_ENROLL = 1;
-    /**
-     * Indicates that we need to un-enroll.
-     *
-     * @hide
-     */
-    public static final int MANAGE_ACTION_UN_ENROLL = 2;
-
     //-- Flags for startRecognition    ----//
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -248,7 +224,8 @@
      * The metadata of the Keyphrase, derived from the enrollment application.
      * This may be null if this keyphrase isn't supported by the enrollment application.
      */
-    private final KeyphraseMetadata mKeyphraseMetadata;
+    @Nullable
+    private KeyphraseMetadata mKeyphraseMetadata;
     private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
     private final IVoiceInteractionService mVoiceInteractionService;
     private final IVoiceInteractionManagerService mModelManagementService;
@@ -448,7 +425,6 @@
         mText = text;
         mLocale = locale;
         mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
-        mKeyphraseMetadata = mKeyphraseEnrollmentInfo.getKeyphraseMetadata(text, locale);
         mExternalCallback = callback;
         mHandler = new MyHandler();
         mInternalCallback = new SoundTriggerListener(mHandler);
@@ -484,8 +460,7 @@
         }
 
         // This method only makes sense if we can actually support a recognition.
-        if (mAvailability != STATE_KEYPHRASE_ENROLLED
-                && mAvailability != STATE_KEYPHRASE_UNENROLLED) {
+        if (mAvailability != STATE_KEYPHRASE_ENROLLED || mKeyphraseMetadata == null) {
             throw new UnsupportedOperationException(
                     "Getting supported recognition modes for the keyphrase is not supported");
         }
@@ -679,7 +654,7 @@
     public Intent createEnrollIntent() {
         if (DBG) Slog.d(TAG, "createEnrollIntent");
         synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_ENROLL);
+            return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_ENROLL);
         }
     }
 
@@ -700,7 +675,7 @@
     public Intent createUnEnrollIntent() {
         if (DBG) Slog.d(TAG, "createUnEnrollIntent");
         synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
+            return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_UN_ENROLL);
         }
     }
 
@@ -721,11 +696,11 @@
     public Intent createReEnrollIntent() {
         if (DBG) Slog.d(TAG, "createReEnrollIntent");
         synchronized (mLock) {
-            return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
+            return getManageIntentLocked(KeyphraseEnrollmentInfo.MANAGE_ACTION_RE_ENROLL);
         }
     }
 
-    private Intent getManageIntentLocked(int action) {
+    private Intent getManageIntentLocked(@KeyphraseEnrollmentInfo.ManageActions int action) {
         if (mAvailability == STATE_INVALID) {
             throw new IllegalStateException("getManageIntent called on an invalid detector");
         }
@@ -761,8 +736,7 @@
     void onSoundModelsChanged() {
         synchronized (mLock) {
             if (mAvailability == STATE_INVALID
-                    || mAvailability == STATE_HARDWARE_UNAVAILABLE
-                    || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
+                    || mAvailability == STATE_HARDWARE_UNAVAILABLE) {
                 Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
                 return;
             }
@@ -772,7 +746,9 @@
             // or was deleted.
             // The availability change callback should ensure that the client starts recognition
             // again if needed.
-            stopRecognitionLocked();
+            if (mAvailability == STATE_KEYPHRASE_ENROLLED) {
+                stopRecognitionLocked();
+            }
 
             // Execute a refresh availability task - which should then notify of a change.
             new RefreshAvailabiltyTask().execute();
@@ -955,20 +931,17 @@
         @Override
         public Void doInBackground(Void... params) {
             int availability = internalGetInitialAvailability();
-            boolean enrolled = false;
-            // Fetch the sound model if the availability is one of the supported ones.
-            if (availability == STATE_NOT_READY
-                    || availability == STATE_KEYPHRASE_UNENROLLED
-                    || availability == STATE_KEYPHRASE_ENROLLED) {
-                enrolled = internalGetIsEnrolled(mKeyphraseMetadata.id, mLocale);
-                if (!enrolled) {
-                    availability = STATE_KEYPHRASE_UNENROLLED;
-                } else {
-                    availability = STATE_KEYPHRASE_ENROLLED;
-                }
-            }
 
             synchronized (mLock) {
+                if (availability == STATE_NOT_READY) {
+                    internalUpdateEnrolledKeyphraseMetadata();
+                    if (mKeyphraseMetadata != null) {
+                        availability = STATE_KEYPHRASE_ENROLLED;
+                    } else {
+                        availability = STATE_KEYPHRASE_UNENROLLED;
+                    }
+                }
+
                 if (DBG) {
                     Slog.d(TAG, "Hotword availability changed from " + mAvailability
                             + " -> " + availability);
@@ -997,28 +970,22 @@
             } catch (RemoteException e) {
                 Slog.w(TAG, "RemoteException in getDspProperties!", e);
             }
+
             // No DSP available
             if (dspModuleProperties == null) {
                 return STATE_HARDWARE_UNAVAILABLE;
             }
-            // No enrollment application supports this keyphrase/locale
-            if (mKeyphraseMetadata == null) {
-                return STATE_KEYPHRASE_UNSUPPORTED;
-            }
+
             return STATE_NOT_READY;
         }
 
-        /**
-         * @return The corresponding {@link KeyphraseSoundModel} or null if none is found.
-         */
-        private boolean internalGetIsEnrolled(int keyphraseId, Locale locale) {
+        private void internalUpdateEnrolledKeyphraseMetadata() {
             try {
-                return mModelManagementService.isEnrolledForKeyphrase(
-                        mVoiceInteractionService, keyphraseId, locale.toLanguageTag());
+                mKeyphraseMetadata = mModelManagementService.getEnrolledKeyphraseMetadata(
+                        mVoiceInteractionService, mText, mLocale.toLanguageTag());
             } catch (RemoteException e) {
-                Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!", e);
+                Slog.w(TAG, "RemoteException in internalUpdateEnrolledKeyphraseMetadata", e);
             }
-            return false;
         }
     }
 
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 36e057f..fc99836 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -16,14 +16,18 @@
 
 package android.service.voice;
 
+import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.app.Service;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
+import android.media.voice.KeyphraseModelManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -304,6 +308,23 @@
     }
 
     /**
+     * Creates an {@link KeyphraseModelManager} to use for enrolling voice models outside of the
+     * pre-bundled system voice models.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
+    @NonNull
+    public final KeyphraseModelManager createKeyphraseModelManager() {
+        if (mSystemService == null) {
+            throw new IllegalStateException("Not available until onReady() is called");
+        }
+        synchronized (mLock) {
+            return new KeyphraseModelManager(mSystemService);
+        }
+    }
+
+    /**
      * @return Details of keyphrases available for enrollment.
      * @hide
      */
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 52b7294..36f2c62 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1137,7 +1137,7 @@
         mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
                 mCallbacks, this, mDispatcherState,
                 WindowManager.LayoutParams.TYPE_VOICE_INTERACTION, Gravity.BOTTOM, true);
-        mWindow.getWindow().setFitWindowInsetsTypes(0 /* types */);
+        mWindow.getWindow().getAttributes().setFitInsetsTypes(0 /* types */);
         mWindow.getWindow().addFlags(
                 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED |
                         WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 9169143..dd78c78 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -869,7 +869,7 @@
                         // Add window
                         mLayout.type = mIWallpaperEngine.mWindowType;
                         mLayout.gravity = Gravity.START|Gravity.TOP;
-                        mLayout.setFitWindowInsetsTypes(0 /* types */);
+                        mLayout.setFitInsetsTypes(0 /* types */);
                         mLayout.setTitle(WallpaperService.this.getClass().getName());
                         mLayout.windowAnimations =
                                 com.android.internal.R.style.Animation_Wallpaper;
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 5737591..6787c46 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -36,6 +36,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 +199,25 @@
     }
 
     /**
+     * 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 {
+            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 +278,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 +440,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/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index eb4af1c..06fccaf 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -44,6 +44,9 @@
     public static final String SETTINGS_FUSE_FLAG = "settings_fuse";
     public static final String NOTIF_CONVO_BYPASS_SHORTCUT_REQ =
             "settings_notif_convo_bypass_shortcut_req";
+    /** @hide */
+    public static final String BACKUP_NO_KV_DATA_CHANGE_CALLS =
+            "backup_enable_no_data_notification_calls";
 
     private static final Map<String, String> DEFAULT_FLAGS;
 
@@ -62,6 +65,9 @@
         DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false");
         DEFAULT_FLAGS.put("settings_conditionals", "false");
         DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
+
+        // Disabled until backup transports support it.
+        DEFAULT_FLAGS.put(BACKUP_NO_KV_DATA_CHANGE_CALLS, "false");
     }
 
     /**
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
index 9f0f246..f5025f7 100644
--- a/core/java/android/util/SparseSetArray.java
+++ b/core/java/android/util/SparseSetArray.java
@@ -37,10 +37,10 @@
             mData.put(n, set);
         }
         if (set.contains(value)) {
-            return true;
+            return false;
         }
         set.add(value);
-        return false;
+        return true;
     }
 
     /**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 904c510..0304328 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -423,10 +423,14 @@
     /**
      * Internal method to create a display.
      * The display created with this method will have a static {@link DisplayAdjustments} applied.
-     * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
-     * or {@link android.hardware.display.DisplayManager#getDisplay}
-     * to get a display object.
+     * Applications should use {@link android.content.Context#getDisplay} with
+     * {@link android.app.Activity} or a context associated with a {@link Display} via
+     * {@link android.content.Context#createDisplayContext(Display)}
+     * to get a display object associated with a {@link android.app.Context}, or
+     * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id.
      *
+     * @see android.content.Context#getDisplay()
+     * @see android.content.Context#createDisplayContext(Display)
      * @hide
      */
     public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 993bdc4..14390f1 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -32,6 +32,7 @@
 import android.os.Bundle;
 import android.os.IRemoteCallback;
 import android.os.ParcelFileDescriptor;
+import android.view.DisplayCutout;
 import android.view.IApplicationToken;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IDockedStackListener;
@@ -111,6 +112,20 @@
 
     // These can only be called when holding the MANAGE_APP_TOKENS permission.
     void setEventDispatching(boolean enabled);
+
+    /** @return {@code true} if this binder is a registered window token. */
+    boolean isWindowToken(in IBinder binder);
+    /**
+     * Adds window token for a given type.
+     *
+     * @param token Token to be registered.
+     * @param type Window type to be used with this token.
+     * @param displayId The ID of the display where this token should be added.
+     * @param packageName The name of package to request to add window token.
+     * @return {@link WindowManagerGlobal#ADD_OKAY} if the addition was successful, an error code
+     *         otherwise.
+     */
+    int addWindowContextToken(IBinder token, int type, int displayId, String packageName);
     void addWindowToken(IBinder token, int type, int displayId);
     void removeWindowToken(IBinder token, int displayId);
     void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
@@ -725,4 +740,17 @@
      * Called when a remote process modifies insets on a display window container.
      */
     void modifyDisplayWindowInsets(int displayId, in InsetsState state);
+
+    /**
+     * Called to get the expected window insets.
+     * TODO(window-context): Remove when new insets flag is available.
+     */
+    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/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 271566a..8d58ee8 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -45,12 +45,25 @@
         mViewRootImpl = viewRootImpl;
     }
 
+    @NonNull
     private InputMethodManagerDelegate getImmDelegate() {
-        if (mDelegate == null) {
-            mDelegate = mViewRootImpl.mContext.getSystemService(
-                    InputMethodManager.class).getDelegate();
+        InputMethodManagerDelegate delegate = mDelegate;
+        if (delegate != null) {
+            return delegate;
         }
-        return mDelegate;
+        delegate = mViewRootImpl.mContext.getSystemService(InputMethodManager.class).getDelegate();
+        mDelegate = delegate;
+        return delegate;
+    }
+
+    /** Called when the view root is moved to a different display. */
+    @UiThread
+    void onMovedToDisplay() {
+        // InputMethodManager managed its instances for different displays. So if the associated
+        // display is changed, the delegate also needs to be refreshed (by getImmDelegate).
+        // See the comment in {@link android.app.SystemServiceRegistry} for InputMethodManager
+        // and {@link android.view.inputmethod.InputMethodManager#forContext}.
+        mDelegate = null;
     }
 
     @UiThread
@@ -103,7 +116,8 @@
         }
 
         boolean forceFocus = false;
-        if (getImmDelegate().isRestartOnNextWindowFocus(true /* reset */)) {
+        final InputMethodManagerDelegate immDelegate = getImmDelegate();
+        if (immDelegate.isRestartOnNextWindowFocus(true /* reset */)) {
             if (DEBUG) Log.v(TAG, "Restarting due to isRestartOnNextWindowFocus as true");
             forceFocus = true;
         }
@@ -111,12 +125,13 @@
         final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView;
         onViewFocusChanged(viewForWindowFocus, true);
 
-        getImmDelegate().startInputAsyncOnWindowFocusGain(viewForWindowFocus,
+        immDelegate.startInputAsyncOnWindowFocusGain(viewForWindowFocus,
                 windowAttribute.softInputMode, windowAttribute.flags, forceFocus);
     }
 
     public boolean checkFocus(boolean forceNewFocus, boolean startInput) {
-        if (!getImmDelegate().isCurrentRootView(mViewRootImpl)
+        final InputMethodManagerDelegate immDelegate = getImmDelegate();
+        if (!immDelegate.isCurrentRootView(mViewRootImpl)
                 || (mServedView == mNextServedView && !forceNewFocus)) {
             return false;
         }
@@ -128,15 +143,16 @@
 
         // Close the connection when no next served view coming.
         if (mNextServedView == null) {
-            getImmDelegate().finishInput();
-            getImmDelegate().closeCurrentIme();
+            immDelegate.finishInput();
+            immDelegate.closeCurrentIme();
             return false;
         }
         mServedView = mNextServedView;
-        getImmDelegate().finishComposingText();
+        immDelegate.finishComposingText();
 
         if (startInput) {
-            getImmDelegate().startInput(StartInputReason.CHECK_FOCUS, null, 0, 0, 0);
+            immDelegate.startInput(StartInputReason.CHECK_FOCUS, null /* focusedView */,
+                    0 /* startInputFlags */, 0 /* softInputMode */, 0 /* windowFlags */);
         }
         return true;
     }
@@ -169,13 +185,14 @@
 
     @UiThread
     void onWindowDismissed() {
-        if (!getImmDelegate().isCurrentRootView(mViewRootImpl)) {
+        final InputMethodManagerDelegate immDelegate = getImmDelegate();
+        if (!immDelegate.isCurrentRootView(mViewRootImpl)) {
             return;
         }
         if (mServedView != null) {
-            getImmDelegate().finishInput();
+            immDelegate.finishInput();
         }
-        getImmDelegate().setCurrentRootView(null);
+        immDelegate.setCurrentRootView(null);
         mHasImeFocus = false;
     }
 
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index f5afd10..405eccd 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -40,6 +40,7 @@
 import android.view.WindowInsetsAnimationCallback.AnimationBounds;
 import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
 import android.view.WindowManager.LayoutParams;
+import android.view.animation.Interpolator;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -84,8 +85,8 @@
     public InsetsAnimationControlImpl(SparseArray<InsetsSourceControl> controls, Rect frame,
             InsetsState state, WindowInsetsAnimationControlListener listener,
             @InsetsType int types,
-            InsetsAnimationControlCallbacks controller, long durationMs, boolean fade,
-            @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+            InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
+            boolean fade, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
         mControls = controls;
         mListener = listener;
         mTypes = types;
@@ -101,8 +102,8 @@
         mFrame = new Rect(frame);
         buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);
 
-        mAnimation = new WindowInsetsAnimationCallback.InsetsAnimation(mTypes,
-                InsetsController.INTERPOLATOR, durationMs);
+        mAnimation = new WindowInsetsAnimationCallback.InsetsAnimation(mTypes, interpolator,
+                durationMs);
         mAnimation.setAlpha(getCurrentAlpha());
         mController.startAnimation(this, listener, types, mAnimation,
                 new AnimationBounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
@@ -196,7 +197,7 @@
             state.getSource(control.getType()).setVisible(shown);
         }
         Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */);
-        setInsetsAndAlpha(insets, 1f /* alpha */, shown ? 1f : 0f /* fraction */);
+        setInsetsAndAlpha(insets, 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 411e910..c6e3835 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -28,6 +28,7 @@
 import android.animation.TypeEvaluator;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.RemoteException;
@@ -145,7 +146,7 @@
             controller.setInsetsAndAlpha(
                     value, 1f /* alpha */, (((DefaultAnimationControlListener)
                             ((InsetsAnimationControlImpl) controller).getListener())
-                                    .getRawProgress()));
+                                    .getRawFraction()));
         }
     }
 
@@ -204,9 +205,8 @@
             mController.finish(mShow);
         }
 
-        protected float getRawProgress() {
-            float fraction = (float) mAnimator.getCurrentPlayTime() / mAnimator.getDuration();
-            return mShow ? fraction : 1 - fraction;
+        protected float getRawFraction() {
+            return (float) mAnimator.getCurrentPlayTime() / mAnimator.getDuration();
         }
 
         protected long getDurationMs() {
@@ -437,27 +437,29 @@
 
     @Override
     public void controlWindowInsetsAnimation(@InsetsType int types, long durationMs,
-            WindowInsetsAnimationControlListener listener) {
-        controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs,
+            @Nullable Interpolator interpolator,
+            @NonNull WindowInsetsAnimationControlListener listener) {
+        controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs, interpolator,
                 ANIMATION_TYPE_USER);
     }
 
     private void controlWindowInsetsAnimation(@InsetsType int types,
             WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs,
-            @AnimationType int animationType) {
+            @Nullable Interpolator interpolator, @AnimationType int animationType) {
         // If the frame of our window doesn't span the entire display, the control API makes very
         // little sense, as we don't deal with negative insets. So just cancel immediately.
         if (!mState.getDisplayFrame().equals(mFrame)) {
             listener.onCancelled();
             return;
         }
-        controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, false /* fade */,
-                animationType, getLayoutInsetsDuringAnimationMode(types));
+        controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator,
+                false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types));
     }
 
     private void controlAnimationUnchecked(@InsetsType int types,
             WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
-            long durationMs, boolean fade, @AnimationType int animationType,
+            long durationMs, Interpolator interpolator, boolean fade,
+            @AnimationType int animationType,
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
         if (types == 0) {
             // nothing to animate.
@@ -488,7 +490,7 @@
         }
 
         final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls,
-                frame, mState, listener, typesReady, this, durationMs, fade,
+                frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
                 layoutInsetsDuringAnimation);
         mRunningAnimations.add(new RunningAnimation(controller, animationType));
     }
@@ -733,7 +735,7 @@
         // and hidden state insets are correct.
         controlAnimationUnchecked(
                 types, listener, mState.getDisplayFrame(), fromIme, listener.getDurationMs(),
-                true /* fade */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
+                INTERPOLATOR, true /* fade */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
                 show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
                         : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
     }
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/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 4f8aecd..71cf051 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -20,15 +20,21 @@
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.graphics.PixelFormat;
 import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
- * Utility class for adding a view hierarchy to a SurfaceControl.
- *
- * See WindowlessWmTest for example usage.
- * @hide
+ * Utility class for adding a View hierarchy to a {@link SurfaceControl}. The View hierarchy
+ * will render in to a root SurfaceControl, and receive input based on the SurfaceControl's
+ * placement on-screen. The primary usage of this class is to embed a View hierarchy from
+ * one process in to another. After the SurfaceControlViewHost has been set up in the embedded
+ * content provider, we can send the {@link SurfaceControlViewHost.SurfacePackage}
+ * to the host process. The host process can then attach the hierarchy to a SurfaceView within
+ * its own by calling
+ * {@link SurfaceView#setChildSurfacePackage}.
  */
-@TestApi
 public class SurfaceControlViewHost {
     private ViewRootImpl mViewRoot;
     private WindowlessWindowManager mWm;
@@ -36,20 +42,52 @@
     private SurfaceControl mSurfaceControl;
 
     /**
-     * @hide
+     * Package encapsulating a Surface hierarchy which contains interactive view
+     * elements. It's expected to get this object from
+     * {@link SurfaceControlViewHost#getSurfacePackage} afterwards it can be embedded within
+     * a SurfaceView by calling {@link SurfaceView#setChildSurfacePackage}.
      */
-    @TestApi
-    public class SurfacePackage {
-        final SurfaceControl mSurfaceControl;
+    public static final class SurfacePackage implements Parcelable {
+        private final SurfaceControl mSurfaceControl;
         // TODO: Accessibility ID goes here
 
         SurfacePackage(SurfaceControl sc) {
             mSurfaceControl = sc;
         }
 
+        private SurfacePackage(Parcel in) {
+            mSurfaceControl = new SurfaceControl();
+            mSurfaceControl.readFromParcel(in);
+        }
+
+        /**
+         * Use {@link SurfaceView#setChildSurfacePackage} or manually fix
+         * accessibility (see SurfaceView implementation).
+         * @hide
+         */
         public @NonNull SurfaceControl getSurfaceControl() {
             return mSurfaceControl;
         }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel out, int flags) {
+            mSurfaceControl.writeToParcel(out, flags);
+        }
+
+        public static final @NonNull Creator<SurfacePackage> CREATOR
+             = new Creator<SurfacePackage>() {
+                     public SurfacePackage createFromParcel(Parcel in) {
+                         return new SurfacePackage(in);
+                     }
+                     public SurfacePackage[] newArray(int size) {
+                         return new SurfacePackage[size];
+                     }
+             };
     }
 
     /** @hide */
@@ -59,17 +97,36 @@
         mViewRoot = new ViewRootImpl(c, d, mWm);
     }
 
-    public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d,
-            @Nullable IBinder hostInputToken) {
+    /**
+     * Construct a new SurfaceControlViewHost. The root Surface will be
+     * allocated internally and is accessible via getSurfacePackage().
+     *
+     * The {@param hostToken} parameter, primarily used for ANR reporting,
+     * must be obtained from whomever will be hosting the embedded hierarchy.
+     * It's accessible from {@link SurfaceView#getHostToken}.
+     *
+     * @param context The Context object for your activity or application.
+     * @param display The Display the hierarchy will be placed on.
+     * @param hostToken The host token, as discussed above.
+     */
+    public SurfaceControlViewHost(@NonNull Context context, @NonNull Display display,
+            @Nullable IBinder hostToken) {
         mSurfaceControl = new SurfaceControl.Builder()
             .setContainerLayer()
             .setName("SurfaceControlViewHost")
             .build();
-        mWm = new WindowlessWindowManager(c.getResources().getConfiguration(), mSurfaceControl,
-                hostInputToken);
-        mViewRoot = new ViewRootImpl(c, d, mWm);
+        mWm = new WindowlessWindowManager(context.getResources().getConfiguration(),
+                mSurfaceControl, hostToken);
+        mViewRoot = new ViewRootImpl(context, display, mWm);
     }
 
+    /**
+     * Return a SurfacePackage for the root SurfaceControl of the embedded hierarchy.
+     * Rather than be directly reparented using {@link SurfaceControl.Transaction} this
+     * SurfacePackage should be passed to {@link SurfaceView#setChildSurfacePackage}
+     * which will not only reparent the Surface, but ensure the accessibility hierarchies
+     * are linked.
+     */
     public @Nullable SurfacePackage getSurfacePackage() {
         if (mSurfaceControl != null) {
             return new SurfacePackage(mSurfaceControl);
@@ -78,10 +135,32 @@
         }
     }
 
-    public void addView(View view, WindowManager.LayoutParams attrs) {
+    /**
+     * @hide
+     */
+    public void addView(@NonNull View view, WindowManager.LayoutParams attrs) {
         mViewRoot.setView(view, attrs, null);
     }
 
+    /**
+     * Set the root view of the SurfaceControlViewHost. This view will render in to
+     * the SurfaceControl, and receive input based on the SurfaceControls positioning on
+     * screen. It will be laid as if it were in a window of the passed in width and height.
+     *
+     * @param view The View to add
+     * @param width The width to layout the View within, in pixels.
+     * @param height The height to layout the View within, in pixels.
+     */
+    public void addView(@NonNull View view, int width, int height) {
+        final WindowManager.LayoutParams lp =
+                new WindowManager.LayoutParams(width, height,
+                        WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
+        addView(view, lp);
+    }
+
+    /**
+     * @hide
+     */
     public void relayout(WindowManager.LayoutParams attrs) {
         mViewRoot.setLayoutParams(attrs, false);
         mViewRoot.setReportNextDraw();
@@ -90,8 +169,27 @@
         });
     }
 
-    public void dispose() {
+    /**
+     * Modify the size of the root view.
+     *
+     * @param width Width in pixels
+     * @param height Height in pixels
+     */
+    public void relayout(int width, int height) {
+        final WindowManager.LayoutParams lp =
+                new WindowManager.LayoutParams(width, height,
+                        WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
+        relayout(width, height);
+    }
+
+    /**
+     * Trigger the tear down of the embedded view hierarchy and release the SurfaceControl.
+     * This will result in onDispatchedFromWindow being dispatched to the embedded view hierarchy
+     * and render the object unusable.
+     */
+    public void release() {
         mViewRoot.dispatchDetachedFromWindow();
+        mSurfaceControl.release();
     }
 
     /**
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0de1a4f..75d5538 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManagerPolicyConstants.APPLICATION_MEDIA_SUBLAYER;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_PANEL_SUBLAYER;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -43,6 +44,7 @@
 import android.util.Log;
 import android.view.SurfaceControl.Transaction;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.SurfaceControlViewHost;
 
 import com.android.internal.view.SurfaceCallbackHelper;
 
@@ -204,6 +206,7 @@
 
     // The token of embedded windowless view hierarchy.
     private IBinder mEmbeddedViewHierarchy;
+    SurfaceControlViewHost.SurfacePackage mSurfacePackage;
 
     public SurfaceView(Context context) {
         this(context, null);
@@ -411,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
@@ -877,6 +881,11 @@
                     } else {
                         mTmpTransaction.hide(mSurfaceControl);
                     }
+
+                    if (mSurfacePackage != null) {
+                        reparentSurfacePackage(mTmpTransaction, mSurfacePackage);
+                    }
+
                     updateBackgroundVisibility(mTmpTransaction);
                     if (mUseAlpha) {
                         mTmpTransaction.setAlpha(mSurfaceControl, alpha);
@@ -1114,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);
         }
 
@@ -1209,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);
@@ -1471,11 +1480,12 @@
     }
 
     /**
-     * @return The token used to identify the windows input channel.
-     * @hide
+     * A token used for constructing {@link SurfaceControlViewHost}. This token should
+     * be passed from the host process to the client process.
+     *
+     * @return The token
      */
-    @TestApi
-    public @Nullable IBinder getInputToken() {
+    public @Nullable IBinder getHostToken() {
         final ViewRootImpl viewRoot = getViewRootImpl();
         if (viewRoot == null) {
             return null;
@@ -1537,6 +1547,33 @@
     }
 
     /**
+     * Display the view-hierarchy embedded within a {@link SurfaceControlViewHost.SurfacePackage}
+     * within this SurfaceView. If this SurfaceView is above it's host Surface (see
+     * {@link #setZOrderOnTop} then the embedded Surface hierarchy will be able to receive
+     * input.
+     *
+     * @param p The SurfacePackage to embed.
+     */
+    public void setChildSurfacePackage(@NonNull SurfaceControlViewHost.SurfacePackage p) {
+        final SurfaceControl sc = p != null ? p.getSurfaceControl() : null;
+        final SurfaceControl lastSc = mSurfacePackage != null ?
+            mSurfacePackage.getSurfaceControl() : null;
+        if (mSurfaceControl != null && lastSc != null) {
+            mTmpTransaction.reparent(lastSc, null).apply();
+        } else if (mSurfaceControl != null) {
+            reparentSurfacePackage(mTmpTransaction, p);
+            mTmpTransaction.apply();
+        }
+        mSurfacePackage = p;
+    }
+
+    private void reparentSurfacePackage(SurfaceControl.Transaction t,
+            SurfaceControlViewHost.SurfacePackage p) {
+        // TODO: Link accessibility IDs here.
+        t.reparent(p.getSurfaceControl(), mSurfaceControl);
+    }
+
+    /**
      * Add the token of embedded view hierarchy. Set {@code null} to clear the embedded view
      * hierarchy.
      *
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 377a764..c5f4faf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -22,7 +22,10 @@
 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.WindowInsetsAnimationCallback.DISPATCH_MODE_CONTINUE_ON_SUBTREE;
+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;
@@ -97,6 +100,7 @@
 import android.util.LayoutDirection;
 import android.util.Log;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 import android.util.Pools.SynchronizedPool;
 import android.util.Property;
 import android.util.SparseArray;
@@ -110,9 +114,11 @@
 import android.view.AccessibilityIterators.TextSegmentIterator;
 import android.view.AccessibilityIterators.WordTextSegmentIterator;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Window.OnContentApplyWindowInsetsListener;
+import android.view.WindowInsets.Type;
 import android.view.WindowInsetsAnimationCallback.AnimationBounds;
 import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
-import android.view.WindowInsetsAnimationCallback.DispatchMode;
+import android.view.WindowManager.LayoutParams;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -140,6 +146,7 @@
 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;
@@ -1510,6 +1517,10 @@
      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
      * that they are optional and should be skipped if the window has
      * requested system UI flags that ignore those insets for layout.
+     * <p>
+     * This is only used for support library as of Android R. The framework now uses
+     * {@link #PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS} such that it can skip the legacy
+     * insets path that loses insets information.
      */
     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
 
@@ -2258,7 +2269,7 @@
      * be extended in the future to hold our own class with more than just
      * a Rect. :)
      */
-    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
+    static final ThreadLocal<Rect> sThreadLocal = ThreadLocal.withInitial(Rect::new);
 
     /**
      * Map used to store views' tags.
@@ -3420,6 +3431,7 @@
      *                          1       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
      *                         1        PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE
      *                         11       PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK
+     *                        1         PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS
      * |-------|-------|-------|-------|
      */
 
@@ -3457,6 +3469,11 @@
             PFLAG4_CONTENT_CAPTURE_IMPORTANCE_IS_CACHED
             | PFLAG4_CONTENT_CAPTURE_IMPORTANCE_CACHED_VALUE;
 
+    /**
+     * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
+     */
+    static final int PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS = 0x000000100;
+
     /* End of masks for mPrivateFlags4 */
 
     /** @hide */
@@ -3506,7 +3523,10 @@
      * requested the system UI (status bar) to be visible (the default).
      *
      * @see #setSystemUiVisibility(int)
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
 
     /**
@@ -3519,7 +3539,11 @@
      * <p>In low profile mode, the status bar and/or navigation icons may dim.
      *
      * @see #setSystemUiVisibility(int)
+     * @deprecated Low profile mode is deprecated. Hide the system bars instead if the application
+     * needs to be in a unobtrusive mode. Use {@link WindowInsetsController#hide(int)} with
+     * {@link Type#systemBars()}.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
 
     /**
@@ -3540,7 +3564,10 @@
      * so that both elements reappear at the same time.
      *
      * @see #setSystemUiVisibility(int)
+     * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#navigationBars()}
+     * instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
 
     /**
@@ -3576,7 +3603,10 @@
      * the book.
      *
      * @see #setSystemUiVisibility(int)
+     * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
+     * instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
 
     /**
@@ -3610,7 +3640,11 @@
      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
      * insets it adds to those given to the application.
+     *
+     * @deprecated Use {@link WindowInsets#getInsetsIgnoringVisibility(int)} instead to retrieve
+     * insets that don't change when system bars change visibility state.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
 
     /**
@@ -3622,6 +3656,11 @@
      * decorations when they are shown.  You can perform layout of your inner
      * UI elements to account for the navigation system UI through the
      * {@link #fitSystemWindows(Rect)} method.
+     *
+     * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
+     * {@link Type#navigationBars()}. For non-floating windows that fill the screen, call
+     * {@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;
 
@@ -3646,7 +3685,13 @@
      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
      * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
+     *
+     * @deprecated For floating windows, use {@link LayoutParams#setFitInsetsTypes(int)} with
+     * {@link Type#statusBars()} ()}. For non-floating windows that fill the screen, call
+     * {@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;
 
     /**
@@ -3656,7 +3701,10 @@
      * user interaction.
      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
      * has an effect when used in combination with that flag.</p>
+     *
+     * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_BARS_BY_SWIPE} instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
 
     /**
@@ -3674,7 +3722,10 @@
      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
      * with one or both of those flags.</p>
+     *
+     * @deprecated Use {@link WindowInsetsController#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE} instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
 
     /**
@@ -3688,7 +3739,9 @@
      *         FLAG_TRANSLUCENT_STATUS}.
      *
      * @see android.R.attr#windowLightStatusBar
+     * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_STATUS_BARS} instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
 
     /**
@@ -3714,7 +3767,9 @@
      *         FLAG_TRANSLUCENT_NAVIGATION}.
      *
      * @see android.R.attr#windowLightNavigationBar
+     * @deprecated Use {@link WindowInsetsController#APPEARANCE_LIGHT_NAVIGATION_BARS} instead.
      */
+    @Deprecated
     public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
 
     /**
@@ -3942,7 +3997,10 @@
 
     /**
      * Flags that can impact the layout in relation to system UI.
+     *
+     * @deprecated System UI layout flags are deprecated.
      */
+    @Deprecated
     public static final int SYSTEM_UI_LAYOUT_FLAGS =
             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
@@ -11020,23 +11078,22 @@
 
     private boolean fitSystemWindowsInt(Rect insets) {
         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
-            mUserPaddingStart = UNDEFINED_PADDING;
-            mUserPaddingEnd = UNDEFINED_PADDING;
             Rect localInsets = sThreadLocal.get();
-            if (localInsets == null) {
-                localInsets = new Rect();
-                sThreadLocal.set(localInsets);
-            }
             boolean res = computeFitSystemWindows(insets, localInsets);
-            mUserPaddingLeftInitial = localInsets.left;
-            mUserPaddingRightInitial = localInsets.right;
-            internalSetPadding(localInsets.left, localInsets.top,
-                    localInsets.right, localInsets.bottom);
+            applyInsets(localInsets);
             return res;
         }
         return false;
     }
 
+    private void applyInsets(Rect insets) {
+        mUserPaddingStart = UNDEFINED_PADDING;
+        mUserPaddingEnd = UNDEFINED_PADDING;
+        mUserPaddingLeftInitial = insets.left;
+        mUserPaddingRightInitial = insets.right;
+        internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
+    }
+
     /**
      * Called when the view should apply {@link WindowInsets} according to its internal policy.
      *
@@ -11063,6 +11120,10 @@
      * @return The supplied insets with any applied insets consumed
      */
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        if ((mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
+                && (mViewFlags & FITS_SYSTEM_WINDOWS) != 0) {
+            return onApplyFrameworkOptionalFitSystemWindows(insets);
+        }
         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
             // We weren't called from within a direct call to fitSystemWindows,
             // call into it as a fallback in case we're in a class that overrides it
@@ -11079,6 +11140,13 @@
         return insets;
     }
 
+    private WindowInsets onApplyFrameworkOptionalFitSystemWindows(WindowInsets insets) {
+        Rect localInsets = sThreadLocal.get();
+        WindowInsets result = computeSystemWindowInsets(insets, localInsets);
+        applyInsets(localInsets);
+        return result;
+    }
+
     /**
      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
      * window insets to this view. The listener's
@@ -11369,16 +11437,23 @@
      * @return Insets that should be passed along to views under this one
      */
     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
-        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
-                || mAttachInfo == null
-                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0)) {
+        boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
+                || (mPrivateFlags4 & PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS) != 0;
+        if (isOptionalFitSystemWindows && mAttachInfo != null) {
+            OnContentApplyWindowInsetsListener listener =
+                    mAttachInfo.mContentOnApplyWindowInsetsListener;
+            if (listener == null) {
+                // The application wants to take care of fitting system window for
+                // the content.
+                outLocalInsets.setEmpty();
+                return in;
+            }
+            Pair<Insets, WindowInsets> result = listener.onContentApplyWindowInsets(in);
+            outLocalInsets.set(result.first.toRect());
+            return result.second;
+        } else {
             outLocalInsets.set(in.getSystemWindowInsetsAsRect());
             return in.consumeSystemWindowInsets().inset(outLocalInsets);
-        } else {
-            // The application wants to take care of fitting system window for
-            // the content.
-            outLocalInsets.setEmpty();
-            return in;
         }
     }
 
@@ -11449,7 +11524,7 @@
     }
 
     /**
-     * For use by PhoneWindow to make its own system window fitting optional.
+     * @see #OPTIONAL_FITS_SYSTEM_WINDOWS
      * @hide
      */
     @UnsupportedAppUsage
@@ -11458,6 +11533,14 @@
     }
 
     /**
+     * @see #PFLAG4_OPTIONAL_FITS_SYSTEM_WINDOWS
+     * @hide
+     */
+    public void makeFrameworkOptionalFitsSystemWindows() {
+        mPrivateFlags4 |= PFLAG4_FRAMEWORK_OPTIONAL_FITS_SYSTEM_WINDOWS;
+    }
+
+    /**
      * Returns the visibility status for this view.
      *
      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
@@ -25743,7 +25826,11 @@
      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
+     *
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public void setSystemUiVisibility(int visibility) {
         if (visibility != mSystemUiVisibility) {
             mSystemUiVisibility = visibility;
@@ -25760,7 +25847,11 @@
      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
+     *
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public int getSystemUiVisibility() {
         return mSystemUiVisibility;
     }
@@ -25770,7 +25861,11 @@
      * the entire window.  This is the combination of the
      * {@link #setSystemUiVisibility(int)} values supplied by all of the
      * views in the window.
+     *
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public int getWindowSystemUiVisibility() {
         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
     }
@@ -25782,14 +25877,22 @@
      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
      * in that this is only telling you about the local request of the window,
      * not the actual values applied by the system.
+     *
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public void onWindowSystemUiVisibilityChanged(int visible) {
     }
 
     /**
      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
      * the view hierarchy.
+     *
+     * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+     * instead.
      */
+    @Deprecated
     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
         onWindowSystemUiVisibilityChanged(visible);
     }
@@ -25797,7 +25900,11 @@
     /**
      * Set a listener to receive callbacks when the visibility of the system bar changes.
      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
+     *
+     * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
+     * by setting a {@link OnApplyWindowInsetsListener} on this view.
      */
+    @Deprecated
     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
@@ -25808,7 +25915,11 @@
     /**
      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
      * the view hierarchy.
+     *
+     * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
+     * by setting a {@link OnApplyWindowInsetsListener} on this view.
      */
+    @Deprecated
     public void dispatchSystemUiVisibilityChanged(int visibility) {
         ListenerInfo li = mListenerInfo;
         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
@@ -28249,7 +28360,11 @@
      * state, not what the application is requesting.
      *
      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
+     *
+     * @deprecated Use {@link WindowInsets#isVisible(int)} to find out about system bar visibilities
+     * by setting a {@link OnApplyWindowInsetsListener} on this view.
      */
+    @Deprecated
     public interface OnSystemUiVisibilityChangeListener {
         /**
          * Called when the status bar changes visibility because of a call to
@@ -28415,6 +28530,7 @@
      * window.
      */
     final static class AttachInfo {
+
         interface Callbacks {
             void playSoundEffect(int effectId);
             boolean performHapticFeedback(int effectId, boolean always);
@@ -28854,6 +28970,11 @@
         ContentCaptureManager mContentCaptureManager;
 
         /**
+         * Listener used to fit content on window level.
+         */
+        OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
+
+        /**
          * Creates a new set of attachment information with the specified
          * events handler and thread.
          *
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e6470a7..4f03ca1 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -55,6 +55,7 @@
 import android.util.Pools.SynchronizedPool;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.view.Window.OnContentApplyWindowInsetsListener;
 import android.view.WindowInsetsAnimationCallback.AnimationBounds;
 import android.view.WindowInsetsAnimationCallback.DispatchMode;
 import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
@@ -1527,6 +1528,19 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void makeFrameworkOptionalFitsSystemWindows() {
+        super.makeFrameworkOptionalFitsSystemWindows();
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            children[i].makeFrameworkOptionalFitsSystemWindows();
+        }
+    }
+
     @Override
     public void dispatchDisplayHint(int hint) {
         super.dispatchDisplayHint(hint);
@@ -1871,6 +1885,7 @@
     }
 
     @Override
+    @Deprecated
     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
         super.dispatchWindowSystemUiVisiblityChanged(visible);
 
@@ -1883,6 +1898,7 @@
     }
 
     @Override
+    @Deprecated
     public void dispatchSystemUiVisibilityChanged(int visible) {
         super.dispatchSystemUiVisibilityChanged(visible);
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 09ebd00..7a93dcc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -122,6 +122,7 @@
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
+import android.view.Window.OnContentApplyWindowInsetsListener;
 import android.view.WindowInsets.Type;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
@@ -755,6 +756,11 @@
         mActivityConfigCallback = callback;
     }
 
+    public void setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener listener) {
+        mAttachInfo.mContentOnApplyWindowInsetsListener = listener;
+        requestFitSystemWindows();
+    }
+
     public void addWindowCallbacks(WindowCallbacks callback) {
         synchronized (mWindowCallbacks) {
             mWindowCallbacks.add(callback);
@@ -1442,6 +1448,7 @@
         // Get new instance of display based on current display adjustments. It may be updated later
         // if moving between the displays also involved a configuration change.
         updateInternalDisplay(displayId, mView.getResources());
+        mImeFocusController.onMovedToDisplay();
         mAttachInfo.mDisplayState = mDisplay.getState();
         // Internal state updated, now notify the view hierarchy.
         mView.dispatchMovedToDisplay(mDisplay, config);
@@ -1726,8 +1733,8 @@
     private void updateBoundsLayer() {
         if (mBoundsLayer != null) {
             setBoundsLayerCrop();
-            mTransaction.deferTransactionUntilSurface(mBoundsLayer,
-                    mSurface, mSurface.getNextFrameNumber())
+            mTransaction.deferTransactionUntil(mBoundsLayer,
+                    getRenderSurfaceControl(), mSurface.getNextFrameNumber())
                     .apply();
         }
     }
@@ -1978,9 +1985,9 @@
             return;
         }
 
-        int types = inOutParams.getFitWindowInsetsTypes();
-        int sides = inOutParams.getFitWindowInsetsSides();
-        boolean ignoreVis = inOutParams.getFitIgnoreVisibility();
+        int types = inOutParams.getFitInsetsTypes();
+        int sides = inOutParams.getFitInsetsSides();
+        boolean ignoreVis = inOutParams.isFitInsetsIgnoringVisibility();
 
         if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
                 || (flags & FLAG_LAYOUT_IN_SCREEN) != 0)
@@ -1997,9 +2004,9 @@
                 && adjust == SOFT_INPUT_ADJUST_RESIZE) {
             types |= Type.ime();
         }
-        inOutParams.setFitWindowInsetsTypes(types);
-        inOutParams.setFitWindowInsetsSides(sides);
-        inOutParams.setFitIgnoreVisibility(ignoreVis);
+        inOutParams.setFitInsetsTypes(types);
+        inOutParams.setFitInsetsSides(sides);
+        inOutParams.setFitInsetsIgnoringVisibility(ignoreVis);
 
         // The fitting of insets are not really controlled by the clients, so we remove the flag.
         inOutParams.privateFlags &= ~PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
@@ -9532,4 +9539,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/Window.java b/core/java/android/view/Window.java
index a1894f3..0ef4e33 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -33,6 +33,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -46,6 +47,9 @@
 import android.transition.Scene;
 import android.transition.Transition;
 import android.transition.TransitionManager;
+import android.util.Pair;
+import android.view.View.OnApplyWindowInsetsListener;
+import android.view.ViewGroup.LayoutParams;
 import android.view.WindowInsets.Side.InsetsSide;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.accessibility.AccessibilityEvent;
@@ -692,6 +696,32 @@
                 int dropCountSinceLastInvocation);
     }
 
+    /**
+     * Listener for applying window insets on the content of a window in a custom way.
+     *
+     * <p>Apps may choose to implement this interface if they want to apply custom policy
+     * to the way that window insets are treated for fitting root-level content views.
+     *
+     * @see Window#setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener)
+     */
+    public interface OnContentApplyWindowInsetsListener {
+
+        /**
+         * Called when the window needs to apply insets on the container of its content view which
+         * are set by calling {@link #setContentView}. The method should determine what insets to
+         * apply on the container of the root level content view and what should be dispatched to
+         * the content view's
+         * {@link View#setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener)} through the view
+         * hierarchy.
+         *
+         * @param insets The root level insets that are about to be dispatched
+         * @return A pair, with the first element containing the insets to apply as margin to the
+         *         root-level content views, and the second element determining what should be
+         *         dispatched to the content view.
+         */
+        @NonNull Pair<Insets, WindowInsets> onContentApplyWindowInsets(
+                @NonNull WindowInsets insets);
+    }
 
     public Window(Context context) {
         mContext = context;
@@ -1281,57 +1311,33 @@
     }
 
     /**
-     * A shortcut for {@link WindowManager.LayoutParams#setFitWindowInsetsTypes(int)}
-     * @hide pending unhide
+     * Sets the listener to be invoked when fitting root-level content views.
+     * <p>
+     * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS}
+     * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and
+     * fits content according to these flags.
+     * </p>
+     * @param contentOnApplyWindowInsetsListener The listener to use for fitting root-level content
+     *                                           views, or {@code null} to disable any kind of
+     *                                           content fitting on the window level and letting the
+     *                                           {@link WindowInsets} pass through to the content
+     *                                           view.
+     * @see OnContentApplyWindowInsetsListener
      */
-    public void setFitWindowInsetsTypes(@InsetsType int types) {
-        final WindowManager.LayoutParams attrs = getAttributes();
-        attrs.setFitWindowInsetsTypes(types);
-        dispatchWindowAttributesChanged(attrs);
+    public void setOnContentApplyWindowInsetsListener(
+            @Nullable OnContentApplyWindowInsetsListener contentOnApplyWindowInsetsListener) {
     }
 
     /**
-     * A shortcut for {@link WindowManager.LayoutParams#setFitWindowInsetsSides(int)}
-     * @hide pending unhide
+     * Resets the listener set via {@link #setOnContentApplyWindowInsetsListener} to the default
+     * state.
+     * <p>
+     * By default, a listener that inspects the now deprecated {@link View#SYSTEM_UI_LAYOUT_FLAGS}
+     * as well the {@link WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} flag is installed and
+     * fits content according to these flags.
+     * </p>
      */
-    public void setFitWindowInsetsSides(@InsetsSide int sides) {
-        final WindowManager.LayoutParams attrs = getAttributes();
-        attrs.setFitWindowInsetsSides(sides);
-        dispatchWindowAttributesChanged(attrs);
-    }
-
-    /**
-     * A shortcut for {@link WindowManager.LayoutParams#setFitIgnoreVisibility(boolean)}
-     * @hide pending unhide
-     */
-    public void setFitIgnoreVisibility(boolean ignore) {
-        final WindowManager.LayoutParams attrs = getAttributes();
-        attrs.setFitIgnoreVisibility(ignore);
-        dispatchWindowAttributesChanged(attrs);
-    }
-
-    /**
-     * A shortcut for {@link WindowManager.LayoutParams#getFitWindowInsetsTypes}
-     * @hide pending unhide
-     */
-    public @InsetsType int getFitWindowInsetsTypes() {
-        return getAttributes().getFitWindowInsetsTypes();
-    }
-
-    /**
-     * A shortcut for {@link WindowManager.LayoutParams#getFitWindowInsetsSides()}
-     * @hide pending unhide
-     */
-    public @InsetsSide int getFitWindowInsetsSides() {
-        return getAttributes().getFitWindowInsetsSides();
-    }
-
-    /**
-     * A shortcut for {@link WindowManager.LayoutParams#getFitIgnoreVisibility()}
-     * @hide pending unhide
-     */
-    public boolean getFitIgnoreVisibility() {
-        return getAttributes().getFitIgnoreVisibility();
+    public void resetOnContentApplyWindowInsetsListener() {
     }
 
     /**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 0a2a45b..a6c311e 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -301,11 +301,14 @@
      * </p>
      *
      * @return The system window insets
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     @NonNull
     public Insets getSystemWindowInsets() {
         Insets result = mCompatIgnoreVisibility
-                ? getMaxInsets(mCompatInsetTypes & ~ime())
+                ? getInsetsIgnoringVisibility(mCompatInsetTypes & ~ime())
                 : getInsets(mCompatInsetTypes);
 
         // We can't query max insets for IME, so we need to add it manually after.
@@ -328,25 +331,26 @@
     }
 
     /**
-     * Returns the maximum amount of insets a specific set of windows can cause, denoted by the
-     * {@code typeMask} bit mask of {@link InsetsType}s.
+     * Returns the insets a specific set of windows can cause, denoted by the
+     * {@code typeMask} bit mask of {@link InsetsType}s, regardless of whether that type is
+     * currently visible or not.
      *
-     * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
+     * <p>The insets represents the area of a a window that that <b>may</b> be partially
      * or fully obscured by the system window identified by {@code type}. This value does not
-     * change based on the visibility state of those elements. for example, if the status bar is
-     * normally shown, but temporarily hidden, the maximum inset will still provide the inset
+     * change based on the visibility state of those elements. For example, if the status bar is
+     * normally shown, but temporarily hidden, the inset returned here will still provide the inset
      * associated with the status bar being shown.</p>
      *
      * @param typeMask Bit mask of {@link InsetsType}s to query the insets for.
      * @return The insets.
      *
-     * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Maximum
-     *                                  insets are not available for this type as the height of the
+     * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Insets are
+     *                                  not available if the IME isn't visible as the height of the
      *                                  IME is dynamic depending on the {@link EditorInfo} of the
      *                                  currently focused view, as well as the UI state of the IME.
      */
     @NonNull
-    public Insets getMaxInsets(@InsetsType int typeMask) throws IllegalArgumentException {
+    public Insets getInsetsIgnoringVisibility(@InsetsType int typeMask) {
         if ((typeMask & IME) != 0) {
             throw new IllegalArgumentException("Unable to query the maximum insets for IME");
         }
@@ -381,7 +385,10 @@
      * </p>
      *
      * @return The left system window inset
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getSystemWindowInsetLeft() {
         return getSystemWindowInsets().left;
     }
@@ -394,7 +401,10 @@
      * </p>
      *
      * @return The top system window inset
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getSystemWindowInsetTop() {
         return getSystemWindowInsets().top;
     }
@@ -407,7 +417,10 @@
      * </p>
      *
      * @return The right system window inset
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getSystemWindowInsetRight() {
         return getSystemWindowInsets().right;
     }
@@ -420,7 +433,10 @@
      * </p>
      *
      * @return The bottom system window inset
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getSystemWindowInsetBottom() {
         return getSystemWindowInsets().bottom;
     }
@@ -433,7 +449,10 @@
      * </p>
      *
      * @return true if any of the system window inset values are nonzero
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public boolean hasSystemWindowInsets() {
         return !getSystemWindowInsets().equals(Insets.NONE);
     }
@@ -594,7 +613,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return The stable insets
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     @NonNull
     public Insets getStableInsets() {
         return getInsets(mTypeMaxInsetsMap, mCompatInsetTypes);
@@ -610,7 +632,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return The top stable inset
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getStableInsetTop() {
         return getStableInsets().top;
     }
@@ -625,7 +650,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return The left stable inset
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getStableInsetLeft() {
         return getStableInsets().left;
     }
@@ -640,7 +668,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return The right stable inset
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getStableInsetRight() {
         return getStableInsets().right;
     }
@@ -655,7 +686,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return The bottom stable inset
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public int getStableInsetBottom() {
         return getStableInsets().bottom;
     }
@@ -670,7 +704,10 @@
      * associated with the status bar being shown.</p>
      *
      * @return true if any of the stable inset values are nonzero
+     * @deprecated Use {@link #getInsetsIgnoringVisibility(int)} with {@link Type#systemBars()}
+     * instead.
      */
+    @Deprecated
     public boolean hasStableInsets() {
         return !getStableInsets().equals(Insets.NONE);
     }
@@ -706,7 +743,9 @@
      * system window insets} by {@link #consumeSystemWindowInsets()}.
      *
      * @see #getMandatorySystemGestureInsets
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#systemGestures()} instead.
      */
+    @Deprecated
     @NonNull
     public Insets getSystemGestureInsets() {
         return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
@@ -734,7 +773,9 @@
      * system window insets} by {@link #consumeSystemWindowInsets()}.
      *
      * @see #getSystemGestureInsets
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#mandatorySystemGestures()} instead.
      */
+    @Deprecated
     @NonNull
     public Insets getMandatorySystemGestureInsets() {
         return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES);
@@ -760,7 +801,10 @@
      *
      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
      * system window insets} by {@link #consumeSystemWindowInsets()}.
+     *
+     * @deprecated Use {@link #getInsets(int)} with {@link Type#tappableElement()} instead.
      */
+    @Deprecated
     @NonNull
     public Insets getTappableElementInsets() {
         return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT);
@@ -985,7 +1029,9 @@
          *
          * @see #getSystemWindowInsets()
          * @return itself
+         * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#systemBars()}.
          */
+        @Deprecated
         @NonNull
         public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
             Preconditions.checkNotNull(systemWindowInsets);
@@ -1003,7 +1049,9 @@
          *
          * @see #getSystemGestureInsets()
          * @return itself
+         * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#systemGestures()}.
          */
+        @Deprecated
         @NonNull
         public Builder setSystemGestureInsets(@NonNull Insets insets) {
             WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, insets);
@@ -1023,7 +1071,10 @@
          *
          * @see #getMandatorySystemGestureInsets()
          * @return itself
+         * @deprecated Use {@link #setInsets(int, Insets)} with
+         *             {@link Type#mandatorySystemGestures()}.
          */
+        @Deprecated
         @NonNull
         public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) {
             WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets);
@@ -1038,7 +1089,9 @@
          *
          * @see #getTappableElementInsets()
          * @return itself
+         * @deprecated Use {@link #setInsets(int, Insets)} with {@link Type#tappableElement()}.
          */
+        @Deprecated
         @NonNull
         public Builder setTappableElementInsets(@NonNull Insets insets) {
             WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets);
@@ -1068,15 +1121,15 @@
         }
 
         /**
-         * Sets the maximum amount of insets a specific window type in pixels.
+         * Sets the insets a specific window type in pixels, while ignoring its visibility state.
          *
-         * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
-         * or fully obscured by the system windows identified by {@code typeMask}. This value does
-         * not change based on the visibility state of those elements. for example, if the status
-         * bar is normally shown, but temporarily hidden, the maximum inset will still provide the
+         * <p>The insets represents the area of a a window that that <b>may</b> be partially
+         * or fully obscured by the system window identified by {@code type}. This value does not
+         * change based on the visibility state of those elements. For example, if the status bar is
+         * normally shown, but temporarily hidden, the inset returned here will still provide the
          * inset associated with the status bar being shown.</p>
          *
-         * @see #getMaxInsets(int)
+         * @see #getInsetsIgnoringVisibility(int)
          *
          * @param typeMask The bitmask of {@link InsetsType} to set the insets for.
          * @param insets The insets to set.
@@ -1090,7 +1143,7 @@
          *                                  state of the IME.
          */
         @NonNull
-        public Builder setMaxInsets(@InsetsType int typeMask, @NonNull Insets insets)
+        public Builder setInsetsIgnoringVisibility(@InsetsType int typeMask, @NonNull Insets insets)
                 throws IllegalArgumentException{
             if (typeMask == IME) {
                 throw new IllegalArgumentException("Maximum inset not available for IME");
@@ -1134,7 +1187,10 @@
          *
          * @see #getStableInsets()
          * @return itself
+         * @deprecated Use {@link #setInsetsIgnoringVisibility(int, Insets)} with
+         *             {@link Type#systemBars()}.
          */
+        @Deprecated
         @NonNull
         public Builder setStableInsets(@NonNull Insets stableInsets) {
             Preconditions.checkNotNull(stableInsets);
@@ -1267,13 +1323,6 @@
         }
 
         /**
-         * @return An insets type representing decor that is being app-controlled.
-         */
-        public static @InsetsType int windowDecor() {
-            return WINDOW_DECOR;
-        }
-
-        /**
          * Returns an insets type representing the system gesture insets.
          *
          * <p>The system gesture insets represent the area of a window where system gestures have
@@ -1309,18 +1358,17 @@
         }
 
         /**
-         * @return All system bars. Includes {@link #statusBars()} as well as
+         * @return All system bars. Includes {@link #statusBars()}, {@link #captionBar()} as well as
          *         {@link #navigationBars()}, but not {@link #ime()}.
          */
         public static @InsetsType int systemBars() {
-            return STATUS_BARS | NAVIGATION_BARS;
+            return STATUS_BARS | NAVIGATION_BARS | CAPTION_BAR;
         }
 
         /**
          * @return All inset types combined.
          *
-         * TODO: Figure out if this makes sense at all, mixing e.g {@link #systemGestures()} and
-         *       {@link #ime()} does not seem very useful.
+         * @hide
          */
         public static @InsetsType int all() {
             return 0xFFFFFFFF;
@@ -1340,7 +1388,6 @@
 
     /**
      * Class that defines different sides for insets.
-     * @hide pending unhide
      */
     public static final class Side {
 
diff --git a/core/java/android/view/WindowInsetsAnimationCallback.java b/core/java/android/view/WindowInsetsAnimationCallback.java
index 53d4939..1e04d02 100644
--- a/core/java/android/view/WindowInsetsAnimationCallback.java
+++ b/core/java/android/view/WindowInsetsAnimationCallback.java
@@ -88,7 +88,7 @@
      * <ul>
      *     <li>Application calls {@link WindowInsetsController#hideInputMethod()},
      *     {@link WindowInsetsController#showInputMethod()},
-     *     {@link WindowInsetsController#controlInputMethodAnimation(long, WindowInsetsAnimationControlListener)}</li>
+     *     {@link WindowInsetsController#controlInputMethodAnimation}</li>
      *     <li>onPrepare is called on the view hierarchy listeners</li>
      *     <li>{@link View#onApplyWindowInsets} will be called with the end state of the
      *     animation</li>
@@ -182,14 +182,26 @@
         private final @InsetsType int mTypeMask;
         private float mFraction;
         @Nullable private final Interpolator mInterpolator;
-        private long mDurationMs;
+        private final long mDurationMillis;
         private float mAlpha;
 
+        /**
+         * Creates a new {@link InsetsAnimation} object.
+         * <p>
+         * This should only be used for testing, as usually the system creates this object for the
+         * application to listen to with {@link WindowInsetsAnimationCallback}.
+         * </p>
+         * @param typeMask The bitmask of {@link WindowInsets.Type}s that are animating.
+         * @param interpolator The interpolator of the animation.
+         * @param durationMillis The duration of the animation in
+         *                   {@link java.util.concurrent.TimeUnit#MILLISECONDS}.
+         */
         public InsetsAnimation(
-                @InsetsType int typeMask, @Nullable Interpolator interpolator, long durationMs) {
+                @InsetsType int typeMask, @Nullable Interpolator interpolator,
+                long durationMillis) {
             mTypeMask = typeMask;
             mInterpolator = interpolator;
-            mDurationMs = durationMs;
+            mDurationMillis = durationMillis;
         }
 
         /**
@@ -201,14 +213,18 @@
 
         /**
          * Returns the raw fractional progress of this animation between
-         * {@link AnimationBounds#getLowerBound()} and {@link AnimationBounds#getUpperBound()}. Note
+         * start state of the animation and the end state of the animation. Note
          * that this progress is the global progress of the animation, whereas
          * {@link WindowInsetsAnimationCallback#onProgress} will only dispatch the insets that may
          * be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
          * Progress per insets animation is global for the entire animation. One animation animates
          * all things together (in, out, ...). If they don't animate together, we'd have
          * multiple animations.
-         *
+         * <p>
+         * Note: In case the application is controlling the animation, the valued returned here will
+         * be the same as the application passed into
+         * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
+         * </p>
          * @return The current progress of this animation.
          */
         @FloatRange(from = 0f, to = 1f)
@@ -218,16 +234,27 @@
 
         /**
          * Returns the interpolated fractional progress of this animation between
-         * {@link AnimationBounds#getLowerBound()} and {@link AnimationBounds#getUpperBound()}. Note
+         * start state of the animation and the end state of the animation. Note
          * that this progress is the global progress of the animation, whereas
          * {@link WindowInsetsAnimationCallback#onProgress} will only dispatch the insets that may
          * be inset with {@link WindowInsets#inset} by parents of views in the hierarchy.
          * Progress per insets animation is global for the entire animation. One animation animates
          * all things together (in, out, ...). If they don't animate together, we'd have
          * multiple animations.
+         * <p>
+         * Note: In case the application is controlling the animation, the valued returned here will
+         * be the same as the application passed into
+         * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)},
+         * interpolated with the interpolator passed into
+         * {@link WindowInsetsController#controlInputMethodAnimation}.
+         * </p>
+         * <p>
+         * Note: For system-initiated animations, this will always return a valid value between 0
+         * and 1.
+         * </p>
          * @see #getFraction() for raw fraction.
          * @return The current interpolated progress of this animation. -1 if interpolator isn't
-         * specified.
+         *         specified.
          */
         public float getInterpolatedFraction() {
             if (mInterpolator != null) {
@@ -236,52 +263,66 @@
             return -1;
         }
 
+        /**
+         * Retrieves the interpolator used for this animation, or {@code null} if this animation
+         * doesn't follow an interpolation curved. For system-initiated animations, this will never
+         * return {@code null}.
+         *
+         * @return The interpolator used for this animation.
+         */
         @Nullable
         public Interpolator getInterpolator() {
             return mInterpolator;
         }
 
         /**
-         * @return duration of animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS}.
+         * @return duration of animation in {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or
+         *         -1 if the animation doesn't have a fixed duration.
          */
         public long getDurationMillis() {
-            return mDurationMs;
+            return mDurationMillis;
         }
 
         /**
          * Set fraction of the progress if {@link WindowInsets.Type.InsetsType} animation is
-         * controlled by the app {@see #getCurrentFraction}.
-         * <p>Note: If app didn't create {@link InsetsAnimation}, it shouldn't set progress either.
-         * Progress would be set by system with the system-default animation.
+         * controlled by the app.
+         * <p>
+         * Note: This should only be used for testing, as the system fills in the fraction for the
+         * application or the fraction that was passed into
+         * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
+         * used.
          * </p>
          * @param fraction fractional progress between 0 and 1 where 0 represents hidden and
          *                zero progress and 1 represent fully shown final state.
+         * @see #getFraction()
          */
         public void setFraction(@FloatRange(from = 0f, to = 1f) float fraction) {
             mFraction = fraction;
         }
 
         /**
-         * Set duration of the animation if {@link WindowInsets.Type.InsetsType} animation is
-         * controlled by the app.
-         * <p>Note: If app didn't create {@link InsetsAnimation}, it shouldn't set duration either.
-         * Duration would be set by system with the system-default animation.
-         * </p>
-         * @param durationMs in {@link java.util.concurrent.TimeUnit#MILLISECONDS}
-         */
-        public void setDuration(long durationMs) {
-            mDurationMs = durationMs;
-        }
-
-        /**
-         * @return alpha of {@link WindowInsets.Type.InsetsType}.
+         * Retrieves the translucency of the windows that are animating.
+         *
+         * @return Alpha of windows that cause insets of type {@link WindowInsets.Type.InsetsType}.
          */
         @FloatRange(from = 0f, to = 1f)
         public float getAlpha() {
             return mAlpha;
         }
 
-        void setAlpha(@FloatRange(from = 0f, to = 1f) float alpha) {
+        /**
+         * Sets the translucency of the windows that are animating.
+         * <p>
+         * Note: This should only be used for testing, as the system fills in the alpha for the
+         * application or the alpha that was passed into
+         * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)} is being
+         * used.
+         * </p>
+         * @param alpha Alpha of windows that cause insets of type
+         *              {@link WindowInsets.Type.InsetsType}.
+         * @see #getAlpha()
+         */
+        public void setAlpha(@FloatRange(from = 0f, to = 1f) float alpha) {
             mAlpha = alpha;
         }
     }
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index f292ca4..02323cf 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -20,8 +20,11 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Insets;
 import android.view.WindowInsets.Type.InsetsType;
+import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
+import android.view.animation.Interpolator;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -79,7 +82,6 @@
      * shown on any user interaction on the corresponding display if navigation bars are hidden by
      * {@link #hide(int)} or
      * {@link WindowInsetsAnimationController#setInsetsAndAlpha(Insets, float, float)}.
-     * @hide
      */
     int BEHAVIOR_SHOW_BARS_BY_TOUCH = 0;
 
@@ -90,7 +92,6 @@
      *
      * <p>When system bars are hidden in this mode, they can be revealed with system gestures, such
      * as swiping from the edge of the screen where the bar is hidden from.</p>
-     * @hide
      */
     int BEHAVIOR_SHOW_BARS_BY_SWIPE = 1;
 
@@ -103,7 +104,6 @@
      * gestures, such as swiping from the edge of the screen where the bar is hidden from. These
      * transient system bars will overlay app’s content, may have some degree of transparency, and
      * will automatically hide after a short timeout.</p>
-     * @hide
      */
     int BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE = 2;
 
@@ -126,7 +126,6 @@
      *
      * @param types A bitmask of {@link InsetsType} specifying what windows the app
      *              would like to make appear on screen.
-     * @hide
      */
     void show(@InsetsType int types);
 
@@ -139,7 +138,6 @@
      *
      * @param types A bitmask of {@link InsetsType} specifying what windows the app
      *              would like to make disappear.
-     * @hide
      */
     void hide(@InsetsType int types);
 
@@ -148,29 +146,50 @@
      * the position of the windows in the system causing insets directly.
      *
      * @param types The {@link InsetsType}s the application has requested to control.
-     * @param durationMillis duration of animation in
+     * @param durationMillis Duration of animation in
      *                       {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or -1 if the
-     *                       animation doesn't have a predetermined duration.
+     *                       animation doesn't have a predetermined duration.T his value will be
+     *                       passed to {@link InsetsAnimation#getDurationMillis()}
+     * @param interpolator The interpolator used for this animation, or {@code null} if this
+     *                     animation doesn't follow an interpolation curve. This value will be
+     *                     passed to {@link InsetsAnimation#getInterpolator()} and used to calculate
+     *                     {@link InsetsAnimation#getInterpolatedFraction()}.
      * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
      *                 windows are ready to be controlled, among other callbacks.
-     * @hide
+     *
+     * @see InsetsAnimation#getFraction()
+     * @see InsetsAnimation#getInterpolatedFraction()
+     * @see InsetsAnimation#getInterpolator()
+     * @see InsetsAnimation#getDurationMillis()
      */
     void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis,
+            @Nullable Interpolator interpolator,
             @NonNull WindowInsetsAnimationControlListener listener);
 
     /**
      * Lets the application control the animation for showing the IME in a frame-by-frame manner by
      * modifying the position of the IME when it's causing insets.
      *
-     * @param durationMillis duration of the animation in
+     * @param durationMillis Duration of the animation in
      *                       {@link java.util.concurrent.TimeUnit#MILLISECONDS}, or -1 if the
-     *                       animation doesn't have a predetermined duration.
+     *                       animation doesn't have a predetermined duration. This value will be
+     *                       passed to {@link InsetsAnimation#getDurationMillis()}
+     * @param interpolator The interpolator used for this animation, or {@code null} if this
+     *                     animation doesn't follow an interpolation curve. This value will be
+     *                     passed to {@link InsetsAnimation#getInterpolator()} and used to calculate
+     *                     {@link InsetsAnimation#getInterpolatedFraction()}.
      * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
      *                 IME are ready to be controlled, among other callbacks.
+     *
+     * @see InsetsAnimation#getFraction()
+     * @see InsetsAnimation#getInterpolatedFraction()
+     * @see InsetsAnimation#getInterpolator()
+     * @see InsetsAnimation#getDurationMillis()
      */
     default void controlInputMethodAnimation(long durationMillis,
+            @Nullable Interpolator interpolator,
             @NonNull WindowInsetsAnimationControlListener listener) {
-        controlWindowInsetsAnimation(ime(), durationMillis, listener);
+        controlWindowInsetsAnimation(ime(), durationMillis, interpolator, listener);
     }
 
     /**
@@ -181,7 +200,7 @@
      * the event by observing {@link View#onApplyWindowInsets} and checking visibility with
      * {@link WindowInsets#isVisible}.
      *
-     * @see #controlInputMethodAnimation(long, WindowInsetsAnimationControlListener)
+     * @see #controlInputMethodAnimation
      * @see #hideInputMethod()
      */
     default void showInputMethod() {
@@ -196,7 +215,7 @@
      * the event by observing {@link View#onApplyWindowInsets} and checking visibility with
      * {@link WindowInsets#isVisible}.
      *
-     * @see #controlInputMethodAnimation(long, WindowInsetsAnimationControlListener)
+     * @see #controlInputMethodAnimation
      * @see #showInputMethod()
      */
     default void hideInputMethod() {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index cd9dee4..55c298e 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -421,7 +421,9 @@
      * </p>
      *
      * @return The display that this window manager is managing.
+     * @deprecated Use {@link Context#getDisplay()} instead.
      */
+    @Deprecated
     public Display getDefaultDisplay();
 
     /**
@@ -435,6 +437,49 @@
     public void removeViewImmediate(View view);
 
     /**
+     * Returns the {@link WindowMetrics} according to the current system state.
+     * <p>
+     * The metrics describe the size of the area the window would occupy with
+     * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
+     * such a window would have.
+     * <p>
+     * The value of this is based on the <b>current</b> windowing state of the system.
+     *
+     * For example, for activities in multi-window mode, the metrics returned are based on the
+     * current bounds that the user has selected for the {@link android.app.Activity Activity}'s
+     * task.
+     *
+     * @see #getMaximumWindowMetrics()
+     * @see WindowMetrics
+     */
+    default @NonNull WindowMetrics getCurrentWindowMetrics() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the largets {@link WindowMetrics} an app may expect in the current system state.
+     * <p>
+     * The metrics describe the size of the largest potential area the window might occupy with
+     * {@link LayoutParams#MATCH_PARENT MATCH_PARENT} width and height, and the {@link WindowInsets}
+     * such a window would have.
+     * <p>
+     * The value of this is based on the largest <b>potential</b> windowing state of the system.
+     *
+     * For example, for activities in multi-window mode, the metrics returned are based on the
+     * what the bounds would be if the user expanded the {@link android.app.Activity Activity}'s
+     * task to cover the entire screen.
+     *
+     * Note that this might still be smaller than the size of the physical display if certain areas
+     * of the display are not available to windows created in this {@link Context}.
+     *
+     * @see #getMaximumWindowMetrics()
+     * @see WindowMetrics
+     */
+    default @NonNull WindowMetrics getMaximumWindowMetrics() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Used to asynchronously request Keyboard Shortcuts from the focused window.
      *
      * @hide
@@ -452,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
@@ -1243,11 +1323,9 @@
          *  the device's screen turned on and bright. */
         public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080;
 
-        /** Window flag: place the window within the entire screen, ignoring
-         *  decorations around the border (such as the status bar).  The
-         *  window must correctly position its contents to take the screen
-         *  decoration into account.  This flag is normally set for you
-         *  by Window as described in {@link Window#setFlags}.
+        /**
+         * Window flag for attached windows: Place the window within the entire screen, ignoring
+         * any constraints from the parent window.
          *
          *  <p>Note: on displays that have a {@link DisplayCutout}, the window may be placed
          *  such that it avoids the {@link DisplayCutout} area if necessary according to the
@@ -1277,11 +1355,21 @@
          * {@link android.R.style#Theme_Holo_Light_NoActionBar_Fullscreen},
          * {@link android.R.style#Theme_DeviceDefault_NoActionBar_Fullscreen}, and
          * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_Fullscreen}.</p>
+         *
+         * @deprecated Use {@link WindowInsetsController#hide(int)} with {@link Type#statusBars()}
+         * instead.
          */
+        @Deprecated
         public static final int FLAG_FULLSCREEN      = 0x00000400;
 
-        /** Window flag: override {@link #FLAG_FULLSCREEN} and force the
-         *  screen decorations (such as the status bar) to be shown. */
+        /**
+         * Window flag: override {@link #FLAG_FULLSCREEN} and force the
+         * screen decorations (such as the status bar) to be shown.
+         *
+         * @deprecated This value became API "by accident", and shouldn't be used by 3rd party
+         * applications.
+         */
+        @Deprecated
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
 
         /** Window flag: turn on dithering when compositing this window to
@@ -1313,13 +1401,18 @@
          * until the finger is released. */
         public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000;
 
-        /** Window flag: a special option only for use in combination with
+        /**
+         * Window flag: a special option only for use in combination with
          * {@link #FLAG_LAYOUT_IN_SCREEN}.  When requesting layout in the
          * screen your window may appear on top of or behind screen decorations
          * such as the status bar.  By also including this flag, the window
          * manager will report the inset rectangle needed to ensure your
          * content is not covered by screen decorations.  This flag is normally
-         * set for you by Window as described in {@link Window#setFlags}.*/
+         * set for you by Window as described in {@link Window#setFlags}
+         *
+         * @deprecated Insets will always be delivered to your application.
+         */
+        @Deprecated
         public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
 
         /** Window flag: When set, input method can't interact with the focusable window
@@ -1505,7 +1598,11 @@
          *
          * <p>Note: For devices that support
          * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE} this flag may be ignored.
+         *
+         * @deprecated Use {@link Window#setStatusBarColor(int)} with a half-translucent color
+         * instead.
          */
+        @Deprecated
         public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;
 
         /**
@@ -1528,7 +1625,11 @@
          * <p>Note: For devices that support
          * {@link android.content.pm.PackageManager#FEATURE_AUTOMOTIVE} this flag can be disabled
          * by the car manufacturers.
+         *
+         * @deprecated Use {@link Window#setNavigationBarColor(int)} with a half-translucent color
+         * instead.
          */
+        @Deprecated
         public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000;
 
         /**
@@ -1558,7 +1659,11 @@
          * overlap with the screen decorations of the parent window such as the navigation bar. By
          * including this flag, the window manager will layout the attached window within the decor
          * frame of the parent window such that it doesn't overlap with screen decorations.
+         *
+         * @deprecated Use {@link #setFitInsetsTypes(int)} to determine whether the attached
+         * window will overlap with system bars.
          */
+        @Deprecated
         public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000;
 
         /**
@@ -1878,13 +1983,6 @@
         public static final int PRIVATE_FLAG_FIT_INSETS_CONTROLLED = 0x10000000;
 
         /**
-         * Flag to indicate that the window only draws the bottom bar background so that we don't
-         * extend it to system bar areas at other sides.
-         * @hide
-         */
-        public static final int PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND = 0x20000000;
-
-        /**
          * An internal annotation for flags that can be specified to {@link #softInputMode}.
          *
          * @hide
@@ -1994,11 +2092,7 @@
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
                         equals = PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
-                        name = "FIT_INSETS_CONTROLLED"),
-                @ViewDebug.FlagToString(
-                        mask = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND,
-                        equals = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND,
-                        name = "ONLY_DRAW_BOTTOM_BAR_BACKGROUND")
+                        name = "FIT_INSETS_CONTROLLED")
         })
         @TestApi
         public int privateFlags;
@@ -2098,7 +2192,11 @@
          * layout parameter flags include {@link #FLAG_FULLSCREEN}, this
          * value for {@link #softInputMode} will be ignored; the window will
          * not resize, but will stay fullscreen.
+         *
+         * @deprecated Use {@link Window#setOnContentApplyWindowInsetsListener} instead with a
+         * listener that fits {@link Type#ime()} instead.
          */
+        @Deprecated
         public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
 
         /** Adjustment option for {@link #softInputMode}: set to have a window
@@ -2393,7 +2491,11 @@
          *
          * @see View#STATUS_BAR_VISIBLE
          * @see View#STATUS_BAR_HIDDEN
+         *
+         * @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
+         * instead.
          */
+        @Deprecated
         public int systemUiVisibility;
 
         /**
@@ -2719,7 +2821,7 @@
                         equals = WINDOW_DECOR,
                         name = "WINDOW_DECOR")
         })
-        private @InsetsType int mFitWindowInsetsTypes = Type.systemBars();
+        private @InsetsType int mFitInsetsTypes = Type.systemBars();
 
         @ViewDebug.ExportedProperty(flagMapping = {
                 @ViewDebug.FlagToString(
@@ -2739,19 +2841,18 @@
                         equals = BOTTOM,
                         name = "BOTTOM")
         })
-        private @InsetsSide int mFitWindowInsetsSides = Side.all();
+        private @InsetsSide int mFitInsetsSides = Side.all();
 
-        private boolean mFitIgnoreVisibility = false;
+        private boolean mFitInsetsIgnoringVisibility = false;
 
         /**
          * Specifies types of insets that this window should avoid overlapping during layout.
          *
          * @param types which types of insets that this window should avoid. The initial value of
          *              this object includes all system bars.
-         * @hide pending unhide
          */
-        public void setFitWindowInsetsTypes(@InsetsType int types) {
-            mFitWindowInsetsTypes = types;
+        public void setFitInsetsTypes(@InsetsType int types) {
+            mFitInsetsTypes = types;
             privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
         }
 
@@ -2760,10 +2861,9 @@
          *
          * @param sides which sides that this window should avoid overlapping with the types
          *              specified. The initial value of this object includes all sides.
-         * @hide pending unhide
          */
-        public void setFitWindowInsetsSides(@InsetsSide int sides) {
-            mFitWindowInsetsSides = sides;
+        public void setFitInsetsSides(@InsetsSide int sides) {
+            mFitInsetsSides = sides;
             privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
         }
 
@@ -2771,36 +2871,32 @@
          * Specifies if this window should fit the window insets no matter they are visible or not.
          *
          * @param ignore if true, this window will fit the given types even if they are not visible.
-         * @hide pending unhide
          */
-        public void setFitIgnoreVisibility(boolean ignore) {
-            mFitIgnoreVisibility = ignore;
+        public void setFitInsetsIgnoringVisibility(boolean ignore) {
+            mFitInsetsIgnoringVisibility = ignore;
             privateFlags |= PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
         }
 
         /**
          * @return the insets types that this window is avoiding overlapping.
-         * @hide pending unhide
          */
-        public @InsetsType int getFitWindowInsetsTypes() {
-            return mFitWindowInsetsTypes;
+        public @InsetsType int getFitInsetsTypes() {
+            return mFitInsetsTypes;
         }
 
         /**
          * @return the sides that this window is avoiding overlapping.
-         * @hide pending unhide
          */
-        public @InsetsSide int getFitWindowInsetsSides() {
-            return mFitWindowInsetsSides;
+        public @InsetsSide int getFitInsetsSides() {
+            return mFitInsetsSides;
         }
 
         /**
          * @return {@code true} if this window fits the window insets no matter they are visible or
          *         not.
-         * @hide pending unhide
          */
-        public boolean getFitIgnoreVisibility() {
-            return mFitIgnoreVisibility;
+        public boolean isFitInsetsIgnoringVisibility() {
+            return mFitInsetsIgnoringVisibility;
         }
 
         public LayoutParams() {
@@ -2966,9 +3062,9 @@
             out.writeLong(hideTimeoutMilliseconds);
             out.writeInt(insetsFlags.appearance);
             out.writeInt(insetsFlags.behavior);
-            out.writeInt(mFitWindowInsetsTypes);
-            out.writeInt(mFitWindowInsetsSides);
-            out.writeBoolean(mFitIgnoreVisibility);
+            out.writeInt(mFitInsetsTypes);
+            out.writeInt(mFitInsetsSides);
+            out.writeBoolean(mFitInsetsIgnoringVisibility);
             out.writeBoolean(preferMinimalPostProcessing);
         }
 
@@ -3027,9 +3123,9 @@
             hideTimeoutMilliseconds = in.readLong();
             insetsFlags.appearance = in.readInt();
             insetsFlags.behavior = in.readInt();
-            mFitWindowInsetsTypes = in.readInt();
-            mFitWindowInsetsSides = in.readInt();
-            mFitIgnoreVisibility = in.readBoolean();
+            mFitInsetsTypes = in.readInt();
+            mFitInsetsSides = in.readInt();
+            mFitInsetsIgnoringVisibility = in.readBoolean();
             preferMinimalPostProcessing = in.readBoolean();
         }
 
@@ -3276,18 +3372,18 @@
                 changes |= INSET_FLAGS_CHANGED;
             }
 
-            if (mFitWindowInsetsTypes != o.mFitWindowInsetsTypes) {
-                mFitWindowInsetsTypes = o.mFitWindowInsetsTypes;
+            if (mFitInsetsTypes != o.mFitInsetsTypes) {
+                mFitInsetsTypes = o.mFitInsetsTypes;
                 changes |= LAYOUT_CHANGED;
             }
 
-            if (mFitWindowInsetsSides != o.mFitWindowInsetsSides) {
-                mFitWindowInsetsSides = o.mFitWindowInsetsSides;
+            if (mFitInsetsSides != o.mFitInsetsSides) {
+                mFitInsetsSides = o.mFitInsetsSides;
                 changes |= LAYOUT_CHANGED;
             }
 
-            if (mFitIgnoreVisibility != o.mFitIgnoreVisibility) {
-                mFitIgnoreVisibility = o.mFitIgnoreVisibility;
+            if (mFitInsetsIgnoringVisibility != o.mFitInsetsIgnoringVisibility) {
+                mFitInsetsIgnoringVisibility = o.mFitInsetsIgnoringVisibility;
                 changes |= LAYOUT_CHANGED;
             }
 
@@ -3449,17 +3545,17 @@
                 sb.append(prefix).append("  bhv=").append(ViewDebug.flagsToString(
                         InsetsFlags.class, "behavior", insetsFlags.behavior));
             }
-            if (mFitWindowInsetsTypes != 0) {
+            if (mFitInsetsTypes != 0) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  fitTypes=").append(ViewDebug.flagsToString(
-                        LayoutParams.class, "mFitWindowInsetsTypes", mFitWindowInsetsTypes));
+                        LayoutParams.class, "mFitInsetsTypes", mFitInsetsTypes));
             }
-            if (mFitWindowInsetsSides != Side.all()) {
+            if (mFitInsetsSides != Side.all()) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  fitSides=").append(ViewDebug.flagsToString(
-                        LayoutParams.class, "mFitWindowInsetsSides", mFitWindowInsetsSides));
+                        LayoutParams.class, "mFitInsetsSides", mFitInsetsSides));
             }
-            if (mFitIgnoreVisibility) {
+            if (mFitInsetsIgnoringVisibility) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  fitIgnoreVis");
             }
@@ -3500,9 +3596,9 @@
             proto.write(SUBTREE_SYSTEM_UI_VISIBILITY_FLAGS, subtreeSystemUiVisibility);
             proto.write(APPEARANCE, insetsFlags.appearance);
             proto.write(BEHAVIOR, insetsFlags.behavior);
-            proto.write(FIT_INSETS_TYPES, mFitWindowInsetsTypes);
-            proto.write(FIT_INSETS_SIDES, mFitWindowInsetsSides);
-            proto.write(FIT_IGNORE_VISIBILITY, mFitIgnoreVisibility);
+            proto.write(FIT_INSETS_TYPES, mFitInsetsTypes);
+            proto.write(FIT_INSETS_SIDES, mFitInsetsSides);
+            proto.write(FIT_IGNORE_VISIBILITY, mFitInsetsIgnoringVisibility);
             proto.end(token);
         }
 
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index cdeeaa4..4365d1f 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,12 +17,17 @@
 package android.view;
 
 import android.annotation.NonNull;
+import android.app.ResourcesManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Point;
+import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.Size;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -62,6 +67,10 @@
 
     private IBinder mDefaultToken;
 
+    private boolean mIsViewAdded;
+    private View mLastView;
+    private WindowManager.LayoutParams mLastParams;
+
     public WindowManagerImpl(Context context) {
         this(context, null);
     }
@@ -93,6 +102,9 @@
     public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
         applyDefaultToken(params);
         mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
+        mIsViewAdded = true;
+        mLastView = view;
+        mLastParams = (WindowManager.LayoutParams) params;
     }
 
     @Override
@@ -201,4 +213,71 @@
         }
         return false;
     }
+
+    @Override
+    public WindowMetrics getCurrentWindowMetrics() {
+        final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
+        final Rect bound = getCurrentBounds(context);
+
+        return new WindowMetrics(toSize(bound), computeWindowInsets());
+    }
+
+    private static Rect getCurrentBounds(Context context) {
+        synchronized (ResourcesManager.getInstance()) {
+            return context.getResources().getConfiguration().windowConfiguration.getBounds();
+        }
+    }
+
+    @Override
+    public WindowMetrics getMaximumWindowMetrics() {
+        return new WindowMetrics(toSize(getMaximumBounds()), computeWindowInsets());
+    }
+
+    private Size toSize(Rect frame) {
+        return new Size(frame.width(), frame.height());
+    }
+
+    private Rect getMaximumBounds() {
+        // TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
+        //  bound after displayArea feature is finished.
+        final Display display = mContext.getDisplay();
+        final Point displaySize = new Point();
+        display.getRealSize(displaySize);
+        return new Rect(0, 0, displaySize.x, displaySize.y);
+    }
+
+    private WindowInsets computeWindowInsets() {
+        // TODO(window-context): This can only be properly implemented
+        //  once we flip the new insets mode flag.
+        if (mParentWindow != null) {
+            if (mParentWindow.getDecorView().isAttachedToWindow()) {
+                return mParentWindow.getDecorView().getViewRootImpl()
+                        .getWindowInsets(true /* forceConstruct */);
+            }
+            return getWindowInsetsFromServer(mParentWindow.getAttributes());
+        }
+        if (mIsViewAdded) {
+            return mLastView.getViewRootImpl().getWindowInsets(true /* forceConstruct */);
+        } else {
+            return getWindowInsetsFromServer(new WindowManager.LayoutParams());
+        }
+
+    }
+
+    private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
+        try {
+            final Rect systemWindowInsets = new Rect();
+            final Rect stableInsets = new Rect();
+            final DisplayCutout.ParcelableWrapper displayCutout =
+                    new DisplayCutout.ParcelableWrapper();
+            WindowManagerGlobal.getWindowManagerService().getWindowInsets(attrs,
+                    mContext.getDisplayId(), systemWindowInsets, stableInsets, displayCutout);
+            return new WindowInsets.Builder()
+                    .setSystemWindowInsets(Insets.of(systemWindowInsets))
+                    .setStableInsets(Insets.of(stableInsets))
+                    .setDisplayCutout(displayCutout.get()).build();
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
 }
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
new file mode 100644
index 0000000..8caf5b7
--- /dev/null
+++ b/core/java/android/view/WindowMetrics.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;
+
+import android.annotation.NonNull;
+import android.util.Size;
+
+/**
+ * Metrics about a Window, consisting of the size and {@link WindowInsets}.
+ * <p>
+ * This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and
+ * {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ * @see WindowInsets#getInsets(int)
+ * @see WindowManager#getCurrentWindowMetrics()
+ * @see WindowManager#getMaximumWindowMetrics()
+ */
+public final class WindowMetrics {
+    private final @NonNull Size mSize;
+    private final @NonNull WindowInsets mWindowInsets;
+
+    public WindowMetrics(@NonNull Size size, @NonNull WindowInsets windowInsets) {
+        mSize = size;
+        mWindowInsets = windowInsets;
+    }
+
+    /**
+     * Returns the size of the window.
+     *
+     * @return window size in pixel.
+     */
+    public @NonNull Size getSize() {
+        return mSize;
+    }
+
+    /**
+     * Returns the {@link WindowInsets} of the window.
+     *
+     * @return the {@link WindowInsets} of the window.
+     */
+    public @NonNull WindowInsets getWindowInsets() {
+        return mWindowInsets;
+    }
+}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 6040abd..81c8383 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,16 @@
 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.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 +53,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 +637,33 @@
     }
 
     /**
+     * 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);
+
+        try {
+            mService.shareData(request,
+                    new DataShareAdapterDelegate(executor, 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 +710,55 @@
     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 DataShareAdapterDelegate(Executor executor, DataShareWriteAdapter adapter) {
+            Preconditions.checkNotNull(executor);
+            Preconditions.checkNotNull(adapter);
+
+            mExecutorReference = new WeakReference<>(executor);
+            mAdapterReference = new WeakReference<>(adapter);
+        }
+
+        @Override
+        public void write(ParcelFileDescriptor destination)
+                throws RemoteException {
+            // TODO(b/148264965): implement this.
+            CancellationSignal cancellationSignal = new CancellationSignal();
+            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..e8d85ac 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -20,6 +20,8 @@
 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 com.android.internal.os.IResultReceiver;
@@ -64,6 +66,11 @@
     void removeData(in DataRemovalRequest request);
 
     /**
+    * Requests sharing of a binary data with the content capture service.
+    */
+    void shareData(in DataShareRequest request, 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/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index a26243c..c80a1ae 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -18,6 +18,8 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.os.Bundle;
@@ -28,7 +30,13 @@
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.Printer;
+import android.view.View;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
 /**
@@ -491,6 +499,238 @@
     @Nullable
     public UserHandle targetInputMethodUser = null;
 
+    @IntDef({TrimPolicy.HEAD, TrimPolicy.TAIL})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface TrimPolicy {
+        int HEAD = 0;
+        int TAIL = 1;
+    }
+
+    /**
+     * The maximum length of initialSurroundingText. When the input text from
+     * {@code setInitialSurroundingText(CharSequence)} is longer than this, trimming shall be
+     * performed to keep memory efficiency.
+     */
+    @VisibleForTesting
+    static final int MEMORY_EFFICIENT_TEXT_LENGTH = 2048;
+    /**
+     * When the input text is longer than {@code #MEMORY_EFFICIENT_TEXT_LENGTH}, we start trimming
+     * the input text into three parts: BeforeCursor, Selection, and AfterCursor. We don't want to
+     * trim the Selection but we also don't want it consumes all available space. Therefore, the
+     * maximum acceptable Selection length is half of {@code #MEMORY_EFFICIENT_TEXT_LENGTH}.
+     */
+    @VisibleForTesting
+    static final int MAX_INITIAL_SELECTION_LENGTH =  MEMORY_EFFICIENT_TEXT_LENGTH / 2;
+
+    @NonNull
+    private InitialSurroundingText mInitialSurroundingText = new InitialSurroundingText();
+
+    /**
+     * Editors may use this method to provide initial input text to IMEs. As the surrounding text
+     * could be used to provide various input assistance, we recommend editors to provide the
+     * complete initial input text in its {@link View#onCreateInputConnection(EditorInfo)} callback.
+     * The supplied text will then be processed to serve {@code #getInitialTextBeforeCursor},
+     * {@code #getInitialSelectedText}, and {@code #getInitialTextBeforeCursor}. System is allowed
+     * to trim {@code sourceText} for various reasons while keeping the most valuable data to IMEs.
+     *
+     * <p><strong>Editor authors: </strong>Providing the initial input text helps reducing IPC calls
+     * for IMEs to provide many modern features right after the connection setup. We recommend
+     * calling this method in your implementation.
+     *
+     * @param sourceText The complete input text.
+     */
+    public void setInitialSurroundingText(@NonNull CharSequence sourceText) {
+        setInitialSurroundingSubText(sourceText, /* subTextStart = */ 0);
+    }
+
+    /**
+     * Editors may use this method to provide initial input text to IMEs. As the surrounding text
+     * could be used to provide various input assistance, we recommend editors to provide the
+     * complete initial input text in its {@link View#onCreateInputConnection(EditorInfo)} callback.
+     * When trimming the input text is needed, call this method instead of
+     * {@code setInitialSurroundingText(CharSequence)} and provide the trimmed position info. Always
+     * try to include the selected text within {@code subText} to give the system best flexibility
+     * to choose where and how to trim {@code subText} when necessary.
+     *
+     * @param subText The input text. When it was trimmed, {@code subTextStart} must be provided
+     *                correctly.
+     * @param subTextStart  The position that the input text got trimmed. For example, when the
+     *                      editor wants to trim out the first 10 chars, subTextStart should be 10.
+     */
+    public void setInitialSurroundingSubText(@NonNull CharSequence subText, int subTextStart) {
+        Preconditions.checkNotNull(subText);
+
+        // Swap selection start and end if necessary.
+        final int subTextSelStart = initialSelStart > initialSelEnd
+                ? initialSelEnd - subTextStart : initialSelStart - subTextStart;
+        final int subTextSelEnd = initialSelStart > initialSelEnd
+                ? initialSelStart - subTextStart : initialSelEnd - subTextStart;
+
+        final int subTextLength = subText.length();
+        // Unknown or invalid selection.
+        if (subTextStart < 0 || subTextSelStart < 0 || subTextSelEnd > subTextLength) {
+            mInitialSurroundingText = new InitialSurroundingText();
+            return;
+        }
+
+        // For privacy protection reason, we don't carry password inputs to IMEs.
+        if (isPasswordInputType(inputType)) {
+            mInitialSurroundingText = new InitialSurroundingText();
+            return;
+        }
+
+        if (subTextLength <= MEMORY_EFFICIENT_TEXT_LENGTH) {
+            mInitialSurroundingText = new InitialSurroundingText(subText, subTextSelStart,
+                    subTextSelEnd);
+            return;
+        }
+
+        // The input text is too long. Let's try to trim it reasonably. Fundamental rules are:
+        // 1. Text before the cursor is the most important information to IMEs.
+        // 2. Text after the cursor is the second important information to IMEs.
+        // 3. Selected text is the least important information but it shall NEVER be truncated.
+        //    When it is too long, just drop it.
+        //
+        // Source: <TextBeforeCursor><Selection><TextAfterCursor>
+        // Possible results:
+        // 1. <(maybeTrimmedAtHead)TextBeforeCursor><Selection><TextAfterCursor(maybeTrimmedAtTail)>
+        // 2. <(maybeTrimmedAtHead)TextBeforeCursor><TextAfterCursor(maybeTrimmedAtTail)>
+        //
+        final int sourceSelLength = subTextSelEnd - subTextSelStart;
+        // When the selected text is too long, drop it.
+        final int newSelLength = (sourceSelLength > MAX_INITIAL_SELECTION_LENGTH)
+                ? 0 : sourceSelLength;
+
+        // Distribute rest of length quota to TextBeforeCursor and TextAfterCursor in 4:1 ratio.
+        final int subTextBeforeCursorLength = subTextSelStart;
+        final int subTextAfterCursorLength = subTextLength - subTextSelEnd;
+        final int maxLengthMinusSelection = MEMORY_EFFICIENT_TEXT_LENGTH - newSelLength;
+        final int possibleMaxBeforeCursorLength =
+                Math.min(subTextBeforeCursorLength, (int) (0.8 * maxLengthMinusSelection));
+        int newAfterCursorLength = Math.min(subTextAfterCursorLength,
+                maxLengthMinusSelection - possibleMaxBeforeCursorLength);
+        int newBeforeCursorLength = Math.min(subTextBeforeCursorLength,
+                maxLengthMinusSelection - newAfterCursorLength);
+
+        // As trimming may happen at the head of TextBeforeCursor, calculate new starting position.
+        int newBeforeCursorHead = subTextBeforeCursorLength - newBeforeCursorLength;
+
+        // We don't want to cut surrogate pairs in the middle. Exam that at the new head and tail.
+        if (isCutOnSurrogate(subText,
+                subTextSelStart - newBeforeCursorLength, TrimPolicy.HEAD)) {
+            newBeforeCursorHead = newBeforeCursorHead + 1;
+            newBeforeCursorLength = newBeforeCursorLength - 1;
+        }
+        if (isCutOnSurrogate(subText,
+                subTextSelEnd + newAfterCursorLength - 1, TrimPolicy.TAIL)) {
+            newAfterCursorLength = newAfterCursorLength - 1;
+        }
+
+        // Now we know where to trim, compose the initialSurroundingText.
+        final int newTextLength = newBeforeCursorLength + newSelLength + newAfterCursorLength;
+        CharSequence newInitialSurroundingText;
+        if (newSelLength != sourceSelLength) {
+            final CharSequence beforeCursor = subText.subSequence(newBeforeCursorHead,
+                    newBeforeCursorHead + newBeforeCursorLength);
+
+            final CharSequence afterCursor = subText.subSequence(subTextSelEnd,
+                    subTextSelEnd + newAfterCursorLength);
+
+            newInitialSurroundingText = TextUtils.concat(beforeCursor, afterCursor);
+        } else {
+            newInitialSurroundingText = subText
+                    .subSequence(newBeforeCursorHead, newBeforeCursorHead + newTextLength);
+        }
+
+        // As trimming may happen at the head, adjust cursor position in the initialSurroundingText
+        // obj.
+        newBeforeCursorHead = 0;
+        final int newSelHead = newBeforeCursorHead + newBeforeCursorLength;
+        mInitialSurroundingText = new InitialSurroundingText(
+                newInitialSurroundingText, newSelHead, newSelHead + newSelLength);
+    }
+
+    /**
+     * Get <var>n</var> characters of text before the current cursor position. May be {@code null}
+     * when the protocol is not supported.
+     *
+     * @param length The expected length of the text.
+     * @param flags Supplies additional options controlling how the text is returned. May be
+     * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
+     * @return the text before the cursor position; the length of the returned text might be less
+     * than <var>n</var>. When there is no text before the cursor, an empty string will be returned.
+     * It could also be {@code null} when the editor or system could not support this protocol.
+     */
+    @Nullable
+    public CharSequence getInitialTextBeforeCursor(int length, int flags) {
+        return mInitialSurroundingText.getInitialTextBeforeCursor(length, flags);
+    }
+
+    /**
+     * Gets the selected text, if any. May be {@code null} when no text is selected or the selected
+     * text is way too long.
+     *
+     * @param flags Supplies additional options controlling how the text is returned. May be
+     * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
+     * @return the text that is currently selected, if any. It could be an empty string when there
+     * is no text selected. When {@code null} is returned, the selected text might be too long or
+     * this protocol is not supported.
+     */
+    @Nullable
+    public CharSequence getInitialSelectedText(int flags) {
+        // Swap selection start and end if necessary.
+        final int correctedTextSelStart = initialSelStart > initialSelEnd
+                ? initialSelEnd : initialSelStart;
+        final int correctedTextSelEnd = initialSelStart > initialSelEnd
+                ? initialSelStart : initialSelEnd;
+
+        final int sourceSelLength = correctedTextSelEnd - correctedTextSelStart;
+        if (initialSelStart < 0 || initialSelEnd < 0
+                || mInitialSurroundingText.getSelectionLength() != sourceSelLength) {
+            return null;
+        }
+        return mInitialSurroundingText.getInitialSelectedText(flags);
+    }
+
+    /**
+     * Get <var>n</var> characters of text after the current cursor position. May be {@code null}
+     * when the protocol is not supported.
+     *
+     * @param length The expected length of the text.
+     * @param flags Supplies additional options controlling how the text is returned. May be
+     * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
+     * @return the text after the cursor position; the length of the returned text might be less
+     * than <var>n</var>. When there is no text after the cursor, an empty string will be returned.
+     * It could also be {@code null} when the editor or system could not support this protocol.
+     */
+    @Nullable
+    public CharSequence getInitialTextAfterCursor(int length, int flags) {
+        return mInitialSurroundingText.getInitialTextAfterCursor(length, flags);
+    }
+
+    private static boolean isCutOnSurrogate(CharSequence sourceText, int cutPosition,
+            @TrimPolicy int policy) {
+        switch (policy) {
+            case TrimPolicy.HEAD:
+                return Character.isLowSurrogate(sourceText.charAt(cutPosition));
+            case TrimPolicy.TAIL:
+                return Character.isHighSurrogate(sourceText.charAt(cutPosition));
+            default:
+                return false;
+        }
+    }
+
+    private static boolean isPasswordInputType(int inputType) {
+        final int variation =
+                inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
+        return variation
+                == (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD)
+                || variation
+                == (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_PASSWORD)
+                || variation
+                == (TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORD);
+    }
+
     /**
      * Ensure that the data in this EditorInfo is compatible with an application
      * that was developed against the given target API version.  This can
@@ -573,6 +813,7 @@
         dest.writeInt(fieldId);
         dest.writeString(fieldName);
         dest.writeBundle(extras);
+        mInitialSurroundingText.writeToParcel(dest, flags);
         if (hintLocales != null) {
             hintLocales.writeToParcel(dest, flags);
         } else {
@@ -603,6 +844,9 @@
                     res.fieldId = source.readInt();
                     res.fieldName = source.readString();
                     res.extras = source.readBundle();
+                    InitialSurroundingText initialSurroundingText =
+                            InitialSurroundingText.CREATOR.createFromParcel(source);
+                    res.mInitialSurroundingText = initialSurroundingText;
                     LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source);
                     res.hintLocales = hintLocales.isEmpty() ? null : hintLocales;
                     res.contentMimeTypes = source.readStringArray();
@@ -619,4 +863,93 @@
         return 0;
     }
 
+    // TODO(b/148035211): Unit tests for this class
+    static final class InitialSurroundingText implements Parcelable {
+        @Nullable final CharSequence mSurroundingText;
+        final int mSelectionHead;
+        final int mSelectionEnd;
+
+        InitialSurroundingText() {
+            mSurroundingText = null;
+            mSelectionHead = 0;
+            mSelectionEnd = 0;
+        }
+
+        InitialSurroundingText(@Nullable CharSequence surroundingText, int selectionHead,
+                int selectionEnd) {
+            mSurroundingText = surroundingText;
+            mSelectionHead = selectionHead;
+            mSelectionEnd = selectionEnd;
+        }
+
+        @Nullable
+        private CharSequence getInitialTextBeforeCursor(int n, int flags) {
+            if (mSurroundingText == null) {
+                return null;
+            }
+
+            final int length = Math.min(n, mSelectionHead);
+            return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
+                    ? mSurroundingText.subSequence(mSelectionHead - length, mSelectionHead)
+                    : TextUtils.substring(mSurroundingText, mSelectionHead - length,
+                            mSelectionHead);
+        }
+
+        @Nullable
+        private CharSequence getInitialSelectedText(int flags) {
+            if (mSurroundingText == null) {
+                return null;
+            }
+
+            return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
+                    ? mSurroundingText.subSequence(mSelectionHead, mSelectionEnd)
+                    : TextUtils.substring(mSurroundingText, mSelectionHead, mSelectionEnd);
+        }
+
+        @Nullable
+        private CharSequence getInitialTextAfterCursor(int n, int flags) {
+            if (mSurroundingText == null) {
+                return null;
+            }
+
+            final int length = Math.min(n, mSurroundingText.length() - mSelectionEnd);
+            return ((flags & InputConnection.GET_TEXT_WITH_STYLES) != 0)
+                    ? mSurroundingText.subSequence(mSelectionEnd, mSelectionEnd + length)
+                    : TextUtils.substring(mSurroundingText, mSelectionEnd, mSelectionEnd + length);
+        }
+
+        private int getSelectionLength() {
+            return mSelectionEnd - mSelectionHead;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            TextUtils.writeToParcel(mSurroundingText, dest, flags);
+            dest.writeInt(mSelectionHead);
+            dest.writeInt(mSelectionEnd);
+        }
+
+        public static final @android.annotation.NonNull Parcelable.Creator<InitialSurroundingText>
+                CREATOR = new Parcelable.Creator<InitialSurroundingText>() {
+                    @Override
+                    public InitialSurroundingText createFromParcel(Parcel source) {
+                        final CharSequence initialText =
+                                TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+                        final int selectionHead = source.readInt();
+                        final int selectionEnd = source.readInt();
+
+                        return new InitialSurroundingText(initialText, selectionHead, selectionEnd);
+                    }
+
+                    @Override
+                    public InitialSurroundingText[] newArray(int size) {
+                        return new InitialSurroundingText[size];
+                    }
+                };
+    }
 }
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/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index e554540..4337ed5 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -158,7 +158,11 @@
      * trigger an IPC round-trip that will take some time. Assume this
      * method consumes a lot of time. Also, please keep in mind the
      * Editor may choose to return less characters than requested even
-     * if they are available for performance reasons.</p>
+     * if they are available for performance reasons. If you are using
+     * this to get the initial text around the cursor, you may consider
+     * using {@link EditorInfo#getInitialTextBeforeCursor(int, int)},
+     * {@link EditorInfo#getInitialSelectedText(int)}, and
+     * {@link EditorInfo#getInitialTextAfterCursor(int, int)} to prevent IPC costs.</p>
      *
      * <p><strong>Editor authors:</strong> please be careful of race
      * conditions in implementing this call. An IME can make a change
@@ -196,7 +200,11 @@
      *
      * <p><strong>IME authors:</strong> please consider this will
      * trigger an IPC round-trip that will take some time. Assume this
-     * method consumes a lot of time.</p>
+     * method consumes a lot of time. If you are using this to get the
+     * initial text around the cursor, you may consider using
+     * {@link EditorInfo#getInitialTextBeforeCursor(int, int)},
+     * {@link EditorInfo#getInitialSelectedText(int)}, and
+     * {@link EditorInfo#getInitialTextAfterCursor(int, int)} to prevent IPC costs.</p>
      *
      * <p><strong>Editor authors:</strong> please be careful of race
      * conditions in implementing this call. An IME can make a change
@@ -234,7 +242,11 @@
      *
      * <p><strong>IME authors:</strong> please consider this will
      * trigger an IPC round-trip that will take some time. Assume this
-     * method consumes a lot of time.</p>
+     * method consumes a lot of time. If you are using this to get the
+     * initial text around the cursor, you may consider using
+     * {@link EditorInfo#getInitialTextBeforeCursor(int, int)},
+     * {@link EditorInfo#getInitialSelectedText(int)}, and
+     * {@link EditorInfo#getInitialTextAfterCursor(int, int)} to prevent IPC costs.</p>
      *
      * <p><strong>Editor authors:</strong> please be careful of race
      * conditions in implementing this call. An IME can make a change
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b10631b..7fd4150 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -391,6 +391,9 @@
     // This can only be true if the text view is editable.
     private boolean mCursorControlEnabled;
 
+    // Specifies whether the new magnifier (with fish-eye effect) is enabled.
+    private final boolean mNewMagnifierEnabled;
+
     Editor(TextView textView) {
         mTextView = textView;
         // Synchronize the filter list, which places the undo input filter at the end.
@@ -401,9 +404,13 @@
 
         mCursorControlEnabled = AppGlobals.getIntCoreSetting(
                 WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0;
+        mNewMagnifierEnabled = AppGlobals.getIntCoreSetting(
+                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, 0) != 0;
         if (TextView.DEBUG_CURSOR) {
             logCursor("Editor", "Cursor control is %s.",
                     mCursorControlEnabled ? "enabled" : "disabled");
+            logCursor("Editor", "New magnifier is %s.",
+                    mNewMagnifierEnabled ? "enabled" : "disabled");
         }
     }
 
@@ -422,7 +429,7 @@
         if (FLAG_USE_MAGNIFIER && mMagnifierAnimator == null) {
             // Lazy creates the magnifier instance because it requires the text height which cannot
             // be measured at the time of Editor instance being created.
-            final Magnifier.Builder builder = shouldUseNewMagnifier()
+            final Magnifier.Builder builder = mNewMagnifierEnabled
                     ? createBuilderWithInlineMagnifierDefaults()
                     : Magnifier.createBuilderWithOldMagnifierDefaults(mTextView);
             mMagnifierAnimator = new MagnifierMotionAnimator(builder.build());
@@ -430,24 +437,28 @@
         return mMagnifierAnimator;
     }
 
-    private boolean shouldUseNewMagnifier() {
-        // TODO: use a separate flag to enable new magnifier.
-        return mCursorControlEnabled;
-    }
-
     private Magnifier.Builder createBuilderWithInlineMagnifierDefaults() {
         final Magnifier.Builder params = new Magnifier.Builder(mTextView);
 
         // TODO: supports changing the height/width dynamically because the text height can be
         // dynamically changed.
+        float zoom = AppGlobals.getFloatCoreSetting(
+                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, 1.5f);
+        float aspectRatio = AppGlobals.getFloatCoreSetting(
+                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, 5.5f);
+        // Avoid invalid/unsupported values.
+        if (zoom < 1.2f || zoom > 1.8f) {
+            zoom = 1.5f;
+        }
+        if (aspectRatio < 3 || aspectRatio > 8) {
+            aspectRatio = 5.5f;
+        }
+
         final Paint.FontMetrics fontMetrics = mTextView.getPaint().getFontMetrics();
         final float sourceHeight = fontMetrics.descent - fontMetrics.ascent;
-        final float zoom = 1.5f;
-        final float widthHeightRatio = 5.5f;
         // Slightly increase the height to avoid tooLargeTextForMagnifier() returns true.
         int height = (int)(sourceHeight * zoom) + 2;
-        int width = (int)(widthHeightRatio * height);
-
+        int width = (int)(aspectRatio * height);
 
         params.setFishEyeStyle()
                 .setSize(width, height)
@@ -4680,11 +4691,11 @@
             }
         };
 
-        private int getPreferredWidth() {
+        protected final int getPreferredWidth() {
             return Math.max(mDrawable.getIntrinsicWidth(), mMinSize);
         }
 
-        private int getPreferredHeight() {
+        protected final int getPreferredHeight() {
             return Math.max(mDrawable.getIntrinsicHeight(), mMinSize);
         }
 
@@ -5089,14 +5100,14 @@
                 mTextView.invalidateCursorPath();
                 suspendBlink();
 
-                if (shouldUseNewMagnifier()) {
+                if (mNewMagnifierEnabled) {
                     // Calculates the line bounds as the content source bounds to the magnifier.
                     Layout layout = mTextView.getLayout();
                     int line = layout.getLineForOffset(getCurrentCursorOffset());
                     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);
@@ -5218,7 +5229,7 @@
         // Whether the popup window is in the invisible state and will be dismissed when finger up.
         private boolean mPendingDismissOnUp = false;
         // The alpha value of the drawable.
-        private final int mDrawableOpacity = 255;
+        private final int mDrawableOpacity;
 
         // Members for toggling the insertion menu in touch through mode.
 
@@ -5239,8 +5250,29 @@
         // of the touch through events.
         private float mTextHeight;
 
-        public InsertionHandleView(Drawable drawable) {
+        // The delta height applied to the insertion handle view.
+        private final int mDeltaHeight;
+
+        InsertionHandleView(Drawable drawable) {
             super(drawable, drawable, com.android.internal.R.id.insertion_handle);
+
+            int deltaHeight = 0;
+            int opacity = 255;
+            if (mCursorControlEnabled) {
+                deltaHeight = AppGlobals.getIntCoreSetting(
+                        WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, 25);
+                opacity = AppGlobals.getIntCoreSetting(
+                        WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, 50);
+                // Avoid invalid/unsupported values.
+                if (deltaHeight < -25 || deltaHeight > 50) {
+                    deltaHeight = 25;
+                }
+                if (opacity < 10 || opacity > 100) {
+                    opacity = 50;
+                }
+            }
+            mDeltaHeight = deltaHeight;
+            mDrawableOpacity = opacity;
         }
 
         private void hideAfterDelay() {
@@ -5293,6 +5325,17 @@
         }
 
         @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            if (mCursorControlEnabled) {
+                final int height = Math.max(
+                        getPreferredHeight() + mDeltaHeight, mDrawable.getIntrinsicHeight());
+                setMeasuredDimension(getPreferredWidth(), height);
+                return;
+            }
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent ev) {
             if (mCursorControlEnabled && FLAG_ENABLE_CURSOR_DRAG) {
                 // Should only enable touch through when cursor drag is enabled.
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 733a775..970d70c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -52,7 +52,6 @@
 import android.view.ViewDebug;
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -307,6 +306,9 @@
         setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
 
         setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
+        // onProgressRefresh() is only called when the progress changes. So we should set
+        // stateDescription during initialization here.
+        super.setStateDescription(formatStateDescription(mProgress));
 
         setSecondaryProgress(a.getInt(
                 R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
@@ -1599,8 +1601,7 @@
     }
 
     void onProgressRefresh(float scale, boolean fromUser, int progress) {
-        if (AccessibilityManager.getInstance(mContext).isEnabled()
-                && mCustomStateDescription == null) {
+        if (mCustomStateDescription == null) {
             super.setStateDescription(formatStateDescription(mProgress));
         }
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 32d3fef..8ce6ee5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8668,6 +8668,7 @@
                 outAttrs.initialSelStart = getSelectionStart();
                 outAttrs.initialSelEnd = getSelectionEnd();
                 outAttrs.initialCapsMode = ic.getCursorCapsMode(getInputType());
+                outAttrs.setInitialSurroundingText(mText);
                 return ic;
             }
         }
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 969bda9..42d7892 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -456,7 +456,7 @@
             params.format = PixelFormat.TRANSLUCENT;
             params.windowAnimations = com.android.internal.R.style.Animation_Toast;
             params.type = WindowManager.LayoutParams.TYPE_TOAST;
-            params.setFitIgnoreVisibility(true);
+            params.setFitInsetsIgnoringVisibility(true);
             params.setTitle("Toast");
             params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java
index fa1e498d..1a8e7a7 100644
--- a/core/java/android/widget/WidgetFlags.java
+++ b/core/java/android/widget/WidgetFlags.java
@@ -35,6 +35,66 @@
      */
     public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control";
 
+    /**
+     * The flag of delta height applies to the insertion handle when cursor control flag is enabled.
+     * The default value is 25.
+     */
+    public static final String INSERTION_HANDLE_DELTA_HEIGHT =
+            "CursorControlFeature__insertion_handle_delta_height";
+
+    /**
+     * The key name used in app core settings for {@link #INSERTION_HANDLE_DELTA_HEIGHT}.
+     */
+    public static final String KEY_INSERTION_HANDLE_DELTA_HEIGHT =
+            "widget__insertion_handle_delta_height";
+
+    /**
+     * The flag of opacity applies to the insertion handle when cursor control flag is enabled.
+     * The opacity value is in the range of {0..100}. The default value is 50.
+     */
+    public static final String INSERTION_HANDLE_OPACITY =
+            "CursorControlFeature__insertion_handle_opacity";
+
+    /**
+     * The key name used in app core settings for {@link #INSERTION_HANDLE_OPACITY}.
+     */
+    public static final String KEY_INSERTION_HANDLE_OPACITY =
+            "widget__insertion_handle_opacity";
+
+    /**
+     * The flag of enabling the new magnifier.
+     */
+    public static final String ENABLE_NEW_MAGNIFIER = "CursorControlFeature__enable_new_magnifier";
+
+    /**
+     * The key name used in app core settings for {@link #ENABLE_NEW_MAGNIFIER}.
+     */
+    public static final String KEY_ENABLE_NEW_MAGNIFIER = "widget__enable_new_magnifier";
+
+    /**
+     * The flag of zoom factor applies to the new magnifier.
+     * The default value is 1.5f.
+     */
+    public static final String MAGNIFIER_ZOOM_FACTOR =
+            "CursorControlFeature__magnifier_zoom_factor";
+
+    /**
+     * The key name used in app core settings for {@link #MAGNIFIER_ZOOM_FACTOR}.
+     */
+    public static final String KEY_MAGNIFIER_ZOOM_FACTOR = "widget__magnifier_zoom_factor";
+
+    /**
+     * The flag of aspect ratio (width/height) applies to the new magnifier.
+     * The default value is 5.5f.
+     */
+    public static final String MAGNIFIER_ASPECT_RATIO =
+            "CursorControlFeature__magnifier_aspect_ratio";
+
+    /**
+     * The key name used in app core settings for {@link #MAGNIFIER_ASPECT_RATIO}.
+     */
+    public static final String KEY_MAGNIFIER_ASPECT_RATIO = "widget__magnifier_aspect_ratio";
+
     private WidgetFlags() {
     }
 }
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index 08022e9..77d8e02 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -26,7 +26,9 @@
 import com.android.internal.widget.PagerAdapter;
 import com.android.internal.widget.ViewPager;
 
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * Skeletal {@link PagerAdapter} implementation of a work or personal profile page for
@@ -34,6 +36,7 @@
  */
 public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
 
+    private static final String TAG = "AbstractMultiProfilePagerAdapter";
     static final int PROFILE_PERSONAL = 0;
     static final int PROFILE_WORK = 1;
     @IntDef({PROFILE_PERSONAL, PROFILE_WORK})
@@ -41,10 +44,17 @@
 
     private final Context mContext;
     private int mCurrentPage;
+    private OnProfileSelectedListener mOnProfileSelectedListener;
+    private Set<Integer> mLoadedPages;
 
     AbstractMultiProfilePagerAdapter(Context context, int currentPage) {
         mContext = Objects.requireNonNull(context);
         mCurrentPage = currentPage;
+        mLoadedPages = new HashSet<>();
+    }
+
+    void setOnProfileSelectedListener(OnProfileSelectedListener listener) {
+        mOnProfileSelectedListener = listener;
     }
 
     Context getContext() {
@@ -57,15 +67,22 @@
      * page and rebuilds the list.
      */
     void setupViewPager(ViewPager viewPager) {
-        viewPager.setCurrentItem(mCurrentPage);
         viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
             @Override
             public void onPageSelected(int position) {
                 mCurrentPage = position;
-                getActiveListAdapter().rebuildList();
+                if (!mLoadedPages.contains(position)) {
+                    getActiveListAdapter().rebuildList();
+                    mLoadedPages.add(position);
+                }
+                if (mOnProfileSelectedListener != null) {
+                    mOnProfileSelectedListener.onProfileSelected(position);
+                }
             }
         });
         viewPager.setAdapter(this);
+        viewPager.setCurrentItem(mCurrentPage);
+        mLoadedPages.add(mCurrentPage);
     }
 
     @Override
@@ -90,7 +107,8 @@
         return mCurrentPage;
     }
 
-    UserHandle getCurrentUserHandle() {
+    @VisibleForTesting
+    public UserHandle getCurrentUserHandle() {
         return getActiveListAdapter().mResolverListController.getUserHandle();
     }
 
@@ -135,16 +153,35 @@
      * <p>This method is meant to be implemented with an implementation-specific return type
      * depending on the adapter type.
      */
-    abstract Object getAdapterForIndex(int pageIndex);
+    @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
@@ -152,7 +189,9 @@
 
     abstract Object getCurrentRootAdapter();
 
-    abstract ViewGroup getCurrentAdapterView();
+    abstract ViewGroup getActiveAdapterView();
+
+    abstract @Nullable ViewGroup getInactiveAdapterView();
 
     protected class ProfileDescriptor {
         final ViewGroup rootView;
@@ -160,4 +199,15 @@
             this.rootView = rootView;
         }
     }
+
+    public interface OnProfileSelectedListener {
+        /**
+         * Callback for when the user changes the active tab from personal to work or vice versa.
+         * <p>This callback is only called when the intent resolver or share sheet shows
+         * the work and personal profiles.
+         * @param profileIndex {@link #PROFILE_PERSONAL} if the personal profile was selected or
+         * {@link #PROFILE_WORK} if the work profile was selected.
+         */
+        void onProfileSelected(int profileIndex);
+    }
 }
\ No newline at end of file
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 9532fae..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;
 
@@ -508,7 +522,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         final long intentReceivedTime = System.currentTimeMillis();
         // This is the only place this value is being set. Effectively final.
-        //TODO(arangelov) - should there be a mIsAppPredictorComponentAvailable flag for work tab?
         mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable();
 
         mIsSuccessfullySelected = false;
@@ -639,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);
 
@@ -689,29 +663,6 @@
                 mResolverDrawerLayout.setOnScrollChangeListener(this::handleScroll);
             }
 
-            final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
-            final float defaultElevation = chooserHeader.getElevation();
-            final float chooserHeaderScrollElevation =
-                    getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation);
-
-            mChooserMultiProfilePagerAdapter.getCurrentAdapterView().addOnScrollListener(
-                    new RecyclerView.OnScrollListener() {
-                        public void onScrollStateChanged(RecyclerView view, int scrollState) {
-                        }
-
-                        public void onScrolled(RecyclerView view, int dx, int dy) {
-                            if (view.getChildCount() > 0) {
-                                View child = view.getLayoutManager().findViewByPosition(0);
-                                if (child == null || child.getTop() < 0) {
-                                    chooserHeader.setElevation(chooserHeaderScrollElevation);
-                                    return;
-                                }
-                            }
-
-                            chooserHeader.setElevation(defaultElevation);
-                        }
-            });
-
             mResolverDrawerLayout.setOnCollapsedChangedListener(
                     new ResolverDrawerLayout.OnCollapsedChangedListener() {
 
@@ -731,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) {
@@ -1284,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();
         }
     }
 
@@ -1330,13 +1329,14 @@
     }
 
     @Override
-    public void onPrepareAdapterView(ResolverListAdapter adapter) {
-        mChooserMultiProfilePagerAdapter.getCurrentAdapterView().setVisibility(View.VISIBLE);
+    public void addUseDifferentAppLabelIfNecessary(ResolverListAdapter adapter) {
+        mChooserMultiProfilePagerAdapter.getActiveAdapterView().setVisibility(View.VISIBLE);
         if (mCallerChooserTargets != null && mCallerChooserTargets.length > 0) {
             mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
                     /* origTarget */ null,
                     Lists.newArrayList(mCallerChooserTargets),
-                    TARGET_TYPE_DEFAULT);
+                    TARGET_TYPE_DEFAULT,
+                    /* directShareShortcutInfoCache */ null);
         }
     }
 
@@ -1565,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++) {
@@ -1589,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);
@@ -1620,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);
@@ -1708,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;
@@ -1724,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()
@@ -1773,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;
@@ -1866,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 =
@@ -1939,7 +1952,8 @@
     }
 
     private void sendClickToAppPredictor(TargetInfo targetInfo) {
-        AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled();
+        AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled(
+                mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
         if (directShareAppPredictor == null) {
             return;
         }
@@ -1961,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;
     }
 
     /**
@@ -1996,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) {
@@ -2040,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();
@@ -2128,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(),
@@ -2202,7 +2242,7 @@
         if (mChooserMultiProfilePagerAdapter == null) {
             return;
         }
-        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getCurrentAdapterView();
+        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getActiveAdapterView();
         ChooserGridAdapter gridAdapter = mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
         if (gridAdapter == null || recyclerView == null) {
             return;
@@ -2321,13 +2361,17 @@
     }
 
     @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
     public void onListRebuilt(ResolverListAdapter listAdapter) {
+        setupScrollListener();
+
         ChooserListAdapter chooserListAdapter = (ChooserListAdapter) listAdapter;
         if (chooserListAdapter.mDisplayList == null
                 || chooserListAdapter.mDisplayList.isEmpty()) {
@@ -2368,6 +2412,34 @@
         }
     }
 
+    private void setupScrollListener() {
+        if (mResolverDrawerLayout == null) {
+            return;
+        }
+        final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
+        final float defaultElevation = chooserHeader.getElevation();
+        final float chooserHeaderScrollElevation =
+                getResources().getDimensionPixelSize(R.dimen.chooser_header_scroll_elevation);
+
+        mChooserMultiProfilePagerAdapter.getActiveAdapterView().addOnScrollListener(
+                new RecyclerView.OnScrollListener() {
+                    public void onScrollStateChanged(RecyclerView view, int scrollState) {
+                    }
+
+                    public void onScrolled(RecyclerView view, int dx, int dy) {
+                        if (view.getChildCount() > 0) {
+                            View child = view.getLayoutManager().findViewByPosition(0);
+                            if (child == null || child.getTop() < 0) {
+                                chooserHeader.setElevation(chooserHeaderScrollElevation);
+                                return;
+                            }
+                        }
+
+                        chooserHeader.setElevation(defaultElevation);
+                    }
+                });
+    }
+
     @Override // ChooserListCommunicator
     public boolean isSendAction(Intent targetIntent) {
         if (targetIntent == null) {
@@ -2475,7 +2547,8 @@
      * row level by this adapter but not on the item level. Individual targets within the row are
      * handled by {@link ChooserListAdapter}
      */
-    final class ChooserGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+    @VisibleForTesting
+    public final class ChooserGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
         private ChooserListAdapter mChooserListAdapter;
         private final LayoutInflater mLayoutInflater;
 
@@ -2905,7 +2978,7 @@
 
             if (mDirectShareViewHolder != null && canExpandDirectShare) {
                 mDirectShareViewHolder.handleScroll(
-                        mChooserMultiProfilePagerAdapter.getCurrentAdapterView(), y, oldy,
+                        mChooserMultiProfilePagerAdapter.getActiveAdapterView(), y, oldy,
                         getMaxTargetsPerRow());
             }
         }
@@ -3151,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() {
@@ -3162,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
@@ -3242,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 a8a676d..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;
         }
     }
@@ -246,11 +256,6 @@
     }
 
     @Override
-    public boolean shouldGetResolvedFilter() {
-        return true;
-    }
-
-    @Override
     public int getCount() {
         return getRankedTargetCount() + getAlphaTargetCount()
                 + getSelectableServiceTargetCount() + getCallerTargetCount();
@@ -388,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");
@@ -417,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++;
@@ -552,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}.
@@ -560,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 7d856e1..663e025 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.app;
 
+import android.annotation.Nullable;
 import android.content.Context;
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
@@ -77,11 +79,24 @@
     }
 
     @Override
-    ChooserActivity.ChooserGridAdapter getAdapterForIndex(int pageIndex) {
+    @VisibleForTesting
+    public ChooserActivity.ChooserGridAdapter getAdapterForIndex(int pageIndex) {
         return mItems[pageIndex].chooserGridAdapter;
     }
 
     @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 =
@@ -121,10 +136,19 @@
     }
 
     @Override
-    RecyclerView getCurrentAdapterView() {
+    RecyclerView getActiveAdapterView() {
         return getListViewForIndex(getCurrentPage());
     }
 
+    @Override
+    @Nullable
+    RecyclerView getInactiveAdapterView() {
+        if (getCount() == 1) {
+            return null;
+        }
+        return getListViewForIndex(1 - getCurrentPage());
+    }
+
     class ChooserProfileDescriptor extends ProfileDescriptor {
         private ChooserActivity.ChooserGridAdapter chooserGridAdapter;
         private RecyclerView recyclerView;
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index be2d1d6..f3b6d29 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -26,6 +26,7 @@
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.IVoiceInteractionSessionListener;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.KeyphraseMetadata;
 import android.hardware.soundtrigger.ModelParams;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.service.voice.IVoiceInteractionService;
@@ -72,8 +73,8 @@
      */
     SoundTrigger.ModuleProperties getDspModuleProperties(in IVoiceInteractionService service);
     /**
-     * Indicates if there's a keyphrase sound model available for the given keyphrase ID.
-     * This performs the check for the current user.
+     * Indicates if there's a keyphrase sound model available for the given keyphrase ID and the
+     * user ID of the caller.
      *
      * @param service The current VoiceInteractionService.
      * @param keyphraseId The unique identifier for the keyphrase.
@@ -82,6 +83,18 @@
     boolean isEnrolledForKeyphrase(IVoiceInteractionService service, int keyphraseId,
             String bcp47Locale);
     /**
+     * Generates KeyphraseMetadata for an enrolled sound model based on keyphrase string, locale,
+     * and the user ID of the caller.
+     *
+     * @param service The current VoiceInteractionService
+     * @param keyphrase Keyphrase text associated with the enrolled model
+     * @param bcp47Locale The BCP47 language tag for the keyphrase's locale.
+     * @return The metadata for the enrolled voice model bassed on the passed in parameters. Null if
+     *         no matching voice model exists.
+     */
+    KeyphraseMetadata getEnrolledKeyphraseMetadata(IVoiceInteractionService service,
+            String keyphrase, String bcp47Locale);
+    /**
      * Starts a recognition for the given keyphrase.
      */
     int startRecognition(in IVoiceInteractionService service, int keyphraseId,
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index b2417b2..30a41d3 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -59,6 +59,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -67,9 +68,12 @@
 import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.Button;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.Space;
+import android.widget.TabHost;
+import android.widget.TabWidget;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -82,6 +86,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.widget.ResolverDrawerLayout;
+import com.android.internal.widget.ViewPager;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -147,7 +152,10 @@
     /**
      * TODO(arangelov): Remove a couple of weeks after work/personal tabs are finalized.
      */
-    static final boolean ENABLE_TABBED_VIEW = false;
+    @VisibleForTesting
+    public static boolean ENABLE_TABBED_VIEW = false;
+    private static final String TAB_TAG_PERSONAL = "personal";
+    private static final String TAB_TAG_WORK = "work";
 
     private final PackageMonitor mPackageMonitor = createPackageMonitor();
 
@@ -418,12 +426,16 @@
             Intent[] initialIntents,
             List<ResolveInfo> rList,
             boolean filterLastUsed) {
+        // We only show the default app for the profile of the current user. The filterLastUsed
+        // flag determines whether to show a default app and that app is not shown in the
+        // resolver list. So filterLastUsed should be false for the other profile.
         ResolverListAdapter personalAdapter = createResolverListAdapter(
                 /* context */ this,
                 /* payloadIntents */ mIntents,
                 initialIntents,
                 rList,
-                filterLastUsed,
+                (filterLastUsed && UserHandle.myUserId()
+                        == getPersonalProfileUserHandle().getIdentifier()),
                 mUseLayoutForBrowsables,
                 /* userHandle */ getPersonalProfileUserHandle());
         ResolverListAdapter workAdapter = createResolverListAdapter(
@@ -431,7 +443,8 @@
                 /* payloadIntents */ mIntents,
                 initialIntents,
                 rList,
-                filterLastUsed,
+                (filterLastUsed && UserHandle.myUserId()
+                        == getWorkProfileUserHandle().getIdentifier()),
                 mUseLayoutForBrowsables,
                 /* userHandle */ getWorkProfileUserHandle());
         return new ResolverMultiProfilePagerAdapter(
@@ -495,12 +508,12 @@
             mFooterSpacer = new Space(getApplicationContext());
         } else {
             ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
-                .getCurrentAdapterView().removeFooterView(mFooterSpacer);
+                .getActiveAdapterView().removeFooterView(mFooterSpacer);
         }
         mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
                                                                    mSystemWindowInsets.bottom));
         ((ResolverMultiProfilePagerAdapter) mMultiProfilePagerAdapter)
-            .getCurrentAdapterView().addFooterView(mFooterSpacer);
+            .getActiveAdapterView().addFooterView(mFooterSpacer);
     }
 
     protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
@@ -530,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,
@@ -817,7 +833,7 @@
 
     public void onButtonClick(View v) {
         final int id = v.getId();
-        ListView listView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
+        ListView listView = (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
         ResolverListAdapter currentListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
         int which = currentListAdapter.hasFilteredItem()
                 ? currentListAdapter.getFilteredPosition()
@@ -898,7 +914,10 @@
 
     @Override // ResolverListCommunicator
     public void onPostListReady(ResolverListAdapter listAdapter) {
-        setHeader();
+        if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
+                == UserHandle.myUserId()) {
+            setHeader();
+        }
         resetButtonBar();
         onListRebuilt(listAdapter);
     }
@@ -913,6 +932,9 @@
                 finish();
             }
         }
+
+        final ItemClickListener listener = new ItemClickListener();
+        setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener);
     }
 
     protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) {
@@ -1082,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
@@ -1094,6 +1119,7 @@
         return true;
     }
 
+    @VisibleForTesting
     public void safelyStartActivity(TargetInfo cti) {
         // We're dispatching intents that might be coming from legacy apps, so
         // don't kill ourselves.
@@ -1222,9 +1248,6 @@
                     + "cannot be null.");
         }
         boolean rebuildCompleted = mMultiProfilePagerAdapter.getActiveListAdapter().rebuildList();
-        if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
-            mMultiProfilePagerAdapter.getInactiveListAdapter().rebuildList();
-        }
         if (useLayoutWithDefault()) {
             mLayoutId = R.layout.resolver_list_with_default;
         } else {
@@ -1272,45 +1295,99 @@
             }
         }
 
-        setupViewVisibilities(count);
+        setupViewVisibilities();
+
+        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            setupProfileTabs();
+        }
+
         return false;
     }
 
-    private void setupViewVisibilities(int count) {
-        if (count == 0
-                && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0) {
-            final TextView emptyView = findViewById(R.id.empty);
-            emptyView.setVisibility(View.VISIBLE);
-            findViewById(R.id.profile_pager).setVisibility(View.GONE);
-        } else {
-            onPrepareAdapterView(mMultiProfilePagerAdapter.getActiveListAdapter());
+    private void setupProfileTabs() {
+        TabHost tabHost = findViewById(R.id.profile_tabhost);
+        tabHost.setup();
+        ViewPager viewPager = findViewById(R.id.profile_pager);
+        TabHost.TabSpec tabSpec = tabHost.newTabSpec(TAB_TAG_PERSONAL)
+                .setContent(R.id.profile_pager)
+                .setIndicator(getString(R.string.resolver_personal_tab));
+        tabHost.addTab(tabSpec);
+
+        tabSpec = tabHost.newTabSpec(TAB_TAG_WORK)
+                .setContent(R.id.profile_pager)
+                .setIndicator(getString(R.string.resolver_work_tab));
+        tabHost.addTab(tabSpec);
+
+        TabWidget tabWidget = tabHost.getTabWidget();
+        tabWidget.setVisibility(View.VISIBLE);
+        resetTabsHeaderStyle(tabWidget);
+        updateActiveTabStyle(tabHost);
+
+        tabHost.setOnTabChangedListener(tabId -> {
+            resetTabsHeaderStyle(tabWidget);
+            updateActiveTabStyle(tabHost);
+            if (TAB_TAG_PERSONAL.equals(tabId)) {
+                viewPager.setCurrentItem(0);
+            } else {
+                viewPager.setCurrentItem(1);
+            }
+            setupViewVisibilities();
+        });
+
+        viewPager.setVisibility(View.VISIBLE);
+        tabHost.setCurrentTab(mMultiProfilePagerAdapter.getCurrentPage());
+        mMultiProfilePagerAdapter.setOnProfileSelectedListener(tabHost::setCurrentTab);
+    }
+
+    private void resetTabsHeaderStyle(TabWidget tabWidget) {
+        for (int i = 0; i < tabWidget.getChildCount(); i++) {
+            TextView title = tabWidget.getChildAt(i).findViewById(android.R.id.title);
+            title.setTextColor(getColor(R.color.resolver_tabs_inactive_color));
+            title.setAllCaps(false);
+        }
+    }
+
+    private void updateActiveTabStyle(TabHost tabHost) {
+        TextView title = tabHost.getTabWidget().getChildAt(tabHost.getCurrentTab())
+                .findViewById(android.R.id.title);
+        title.setTextColor(getColor(R.color.resolver_tabs_active_color));
+    }
+
+    private void setupViewVisibilities() {
+        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
+        boolean shouldShowEmptyState = count == 0
+                && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0;
+        //TODO(arangelov): Handle empty state
+        if (!shouldShowEmptyState) {
+            addUseDifferentAppLabelIfNecessary(mMultiProfilePagerAdapter.getActiveListAdapter());
         }
     }
 
     /**
-     * Prepare the scrollable view which consumes data in the list adapter.
+     * Add a label to signify that the user can pick a different app.
      * @param adapter The adapter used to provide data to item views.
      */
-    public void onPrepareAdapterView(ResolverListAdapter adapter) {
-        mMultiProfilePagerAdapter.getCurrentAdapterView().setVisibility(View.VISIBLE);
+    public void addUseDifferentAppLabelIfNecessary(ResolverListAdapter adapter) {
         final boolean useHeader = adapter.hasFilteredItem();
-        final ListView listView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
-        final ItemClickListener listener = new ItemClickListener();
+        if (useHeader) {
+            FrameLayout stub = findViewById(R.id.stub);
+            stub.setVisibility(View.VISIBLE);
+            TextView textView = (TextView) LayoutInflater.from(this).inflate(
+                    R.layout.resolver_different_item_header, null, false);
+            if (ENABLE_TABBED_VIEW) {
+                textView.setGravity(Gravity.CENTER);
+            }
+            stub.addView(textView);
+        }
+    }
+
+    private void setupAdapterListView(ListView listView, ItemClickListener listener) {
         listView.setOnItemClickListener(listener);
         listView.setOnItemLongClickListener(listener);
 
         if (mSupportsAlwaysUseOption || mUseLayoutForBrowsables) {
             listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
         }
-
-        // In case this method is called again (due to activity recreation), avoid adding a new
-        // header if one is already present.
-        if (useHeader && listView.getHeaderViewsCount() == 0) {
-            listView.setHeaderDividersEnabled(true);
-            listView.addHeaderView(LayoutInflater.from(this).inflate(
-                    R.layout.resolver_different_item_header, listView, false),
-                    null, false);
-        }
     }
 
     /**
@@ -1378,7 +1455,7 @@
         }
 
         // When the items load in, if an item was already selected, enable the buttons
-        ListView currentAdapterView = (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
+        ListView currentAdapterView = (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
         if (currentAdapterView != null
                 && currentAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
             setAlwaysButtonEnabled(true, currentAdapterView.getCheckedItemPosition(), true);
@@ -1388,8 +1465,18 @@
 
     @Override // ResolverListCommunicator
     public boolean useLayoutWithDefault() {
-        return mSupportsAlwaysUseOption
-                && mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
+        // We only use the default app layout when the profile of the active user has a
+        // filtered item. We always show the same default app even in the inactive user profile.
+        boolean currentUserAdapterHasFilteredItem;
+        if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
+                == UserHandle.myUserId()) {
+            currentUserAdapterHasFilteredItem =
+                    mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
+        } else {
+            currentUserAdapterHasFilteredItem =
+                    mMultiProfilePagerAdapter.getInactiveListAdapter().hasFilteredItem();
+        }
+        return mSupportsAlwaysUseOption && currentUserAdapterHasFilteredItem;
     }
 
     /**
@@ -1494,9 +1581,8 @@
                     .resolveInfoForPosition(position, true) == null) {
                 return;
             }
-
             ListView currentAdapterView =
-                    (ListView) mMultiProfilePagerAdapter.getCurrentAdapterView();
+                    (ListView) mMultiProfilePagerAdapter.getActiveAdapterView();
             final int checkedPos = currentAdapterView.getCheckedItemPosition();
             final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
             if (!useLayoutWithDefault()
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index ef7a347..405112d 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -193,7 +193,8 @@
                     mBaseResolveList);
         } else {
             currentResolveList = mUnfilteredResolveList =
-                    mResolverListController.getResolversForIntent(shouldGetResolvedFilter(),
+                    mResolverListController.getResolversForIntent(
+                            /* shouldGetResolvedFilter= */ true,
                             mResolverListCommunicator.shouldGetActivityMetadata(),
                             mIntents);
             if (currentResolveList == null) {
@@ -363,10 +364,6 @@
         }
     }
 
-    public boolean shouldGetResolvedFilter() {
-        return mFilterLastUsed;
-    }
-
     private void addResolveInfoWithAlternates(ResolvedComponentInfo rci) {
         final int count = rci.getCount();
         final Intent intent = rci.getIntentAt(0);
@@ -410,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.
@@ -578,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) {
@@ -588,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/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index abd3eb2..0bfe9eb 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -133,7 +133,8 @@
         return resolvedComponents;
     }
 
-    UserHandle getUserHandle() {
+    @VisibleForTesting
+    public UserHandle getUserHandle() {
         return mUserHandle;
     }
 
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index d72c52b..9d3c6c9 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -16,7 +16,9 @@
 
 package com.android.internal.app;
 
+import android.annotation.Nullable;
 import android.content.Context;
+import android.os.UserHandle;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 import android.widget.ListView;
@@ -81,11 +83,24 @@
     }
 
     @Override
-    ResolverListAdapter getAdapterForIndex(int pageIndex) {
+    @VisibleForTesting
+    public ResolverListAdapter getAdapterForIndex(int pageIndex) {
         return mItems[pageIndex].resolverListAdapter;
     }
 
     @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());
@@ -106,10 +121,19 @@
     }
 
     @Override
-    ListView getCurrentAdapterView() {
+    ListView getActiveAdapterView() {
         return getListViewForIndex(getCurrentPage());
     }
 
+    @Override
+    @Nullable
+    ViewGroup getInactiveAdapterView() {
+        if (getCount() == 1) {
+            return null;
+        }
+        return getListViewForIndex(1 - getCurrentPage());
+    }
+
     class ResolverProfileDescriptor extends ProfileDescriptor {
         private ResolverListAdapter resolverListAdapter;
         final ListView listView;
diff --git a/core/java/com/android/internal/app/WrapHeightViewPager.java b/core/java/com/android/internal/app/ResolverViewPager.java
similarity index 74%
rename from core/java/com/android/internal/app/WrapHeightViewPager.java
rename to core/java/com/android/internal/app/ResolverViewPager.java
index b017bb4..8ec94f1 100644
--- a/core/java/com/android/internal/app/WrapHeightViewPager.java
+++ b/core/java/com/android/internal/app/ResolverViewPager.java
@@ -18,39 +18,36 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 
 import com.android.internal.widget.ViewPager;
 
 /**
- * A {@link ViewPager} which wraps around its first child's height.
+ * A {@link ViewPager} which wraps around its first child's height and has swiping disabled.
  * <p>Normally {@link ViewPager} instances expand their height to cover all remaining space in
  * the layout.
- * <p>This class is used for the intent resolver picker's tabbed view to maintain
- * consistency with the previous behavior.
+ * <p>This class is used for the intent resolver and share sheet's tabbed view.
  */
-public class WrapHeightViewPager extends ViewPager {
+public class ResolverViewPager extends ViewPager {
 
-    public WrapHeightViewPager(Context context) {
+    public ResolverViewPager(Context context) {
         super(context);
     }
 
-    public WrapHeightViewPager(Context context, AttributeSet attrs) {
+    public ResolverViewPager(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public WrapHeightViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
+    public ResolverViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
 
-    public WrapHeightViewPager(Context context, AttributeSet attrs,
+    public ResolverViewPager(Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
-    // TODO(arangelov): When we have multiple pages, the height should wrap to the currently
-    // displayed page. Investigate whether onMeasure is called when changing a page, and instead
-    // of getChildAt(0), use the currently displayed one.
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -68,4 +65,14 @@
         heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        return false;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return false;
+    }
 }
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/car/ICarStatsService.aidl b/core/java/com/android/internal/car/ICarStatsService.aidl
deleted file mode 100644
index 170b448..0000000
--- a/core/java/com/android/internal/car/ICarStatsService.aidl
+++ /dev/null
@@ -1,31 +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.internal.car;
-
-import android.os.StatsLogEventWrapper;
-
-/**
- * Interface for pulling statsd atoms from automotive devices.
- *
- * @hide
- */
-interface ICarStatsService {
-    /**
-     * Pull the specified atom. Results will be sent to statsd when complete.
-     */
-    StatsLogEventWrapper[] pullData(int atomId);
-}
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/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 5e3c5df..7a9b659 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -753,6 +753,8 @@
         proto.write(CpuUsageProto.Load.LOAD15, mLoad15);
         proto.end(currentLoadToken);
 
+        buildWorkingProcs();
+
         proto.write(CpuUsageProto.NOW, now);
         proto.write(CpuUsageProto.LAST_SAMPLE_TIME, mLastSampleTime);
         proto.write(CpuUsageProto.CURRENT_SAMPLE_TIME, mCurrentSampleTime);
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 a6637a2..adb4036 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -68,6 +68,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.InsetDrawable;
 import android.graphics.drawable.LayerDrawable;
+import android.os.Build.VERSION_CODES;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
@@ -94,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;
@@ -130,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
 
@@ -282,6 +281,11 @@
     private Insets mLastBackgroundInsets = Insets.NONE;
     private boolean mDrawLegacyNavigationBarBackground;
 
+    /**
+     * Whether the app targets an SDK that uses the new insets APIs.
+     */
+    private boolean mUseNewInsetsApi;
+
     DecorView(Context context, int featureId, PhoneWindow window,
             WindowManager.LayoutParams params) {
         super(context);
@@ -311,6 +315,7 @@
         initResizingPaints();
 
         mLegacyNavigationBarBackgroundPaint.setColor(Color.BLACK);
+        mUseNewInsetsApi = context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.R;
     }
 
     void setBackgroundFallback(@Nullable Drawable fallbackDrawable) {
@@ -1174,20 +1179,24 @@
         // Note: We don't need to check for IN_SCREEN or INSET_DECOR because unlike the status bar,
         // these flags wouldn't make the window draw behind the navigation bar, unless
         // LAYOUT_HIDE_NAVIGATION was set.
+        //
+        // Note: Once the app targets R+, we no longer do this logic because we can't rely on
+        // SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION to indicate whether the app wants to handle it by
+        // themselves.
         boolean hideNavigation = (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
                 || !(state == null || state.getSource(ITYPE_NAVIGATION_BAR).isVisible());
         boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds
                         && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
                         && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
-                        && (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) != 0
                         && !hideNavigation)
                 || (mLastShouldAlwaysConsumeSystemBars && hideNavigation);
 
         boolean consumingNavBar =
                 ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
                         && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
-                        && (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) != 0
-                        && !hideNavigation)
+                        && !hideNavigation
+                        // TODO IME wrap_content windows need to have margin to work properly
+                        && (!mUseNewInsetsApi || isImeWindow))
                 || forceConsumingNavBar;
 
         // If we didn't request fullscreen layout, but we still got it because of the
@@ -1200,16 +1209,14 @@
         boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
                 && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
                 && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
-                && (attrs.getFitWindowInsetsTypes() & Type.statusBars()) != 0
                 && mForceWindowDrawsBarBackgrounds
                 && mLastTopInset != 0
                 || (mLastShouldAlwaysConsumeSystemBars && fullscreen);
 
-        int sides = attrs.getFitWindowInsetsSides();
-        int consumedTop = consumingStatusBar && (sides & Side.TOP) != 0 ? mLastTopInset : 0;
-        int consumedRight = consumingNavBar && (sides & Side.RIGHT) != 0 ? mLastRightInset : 0;
-        int consumedBottom = consumingNavBar && (sides & Side.BOTTOM) != 0 ? mLastBottomInset : 0;
-        int consumedLeft = consumingNavBar && (sides & Side.LEFT) != 0 ? mLastLeftInset : 0;
+        int consumedTop = consumingStatusBar ? mLastTopInset : 0;
+        int consumedRight = consumingNavBar ? mLastRightInset : 0;
+        int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
+        int consumedLeft = consumingNavBar ? mLastLeftInset : 0;
 
         if (mContentRoot != null
                 && mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
@@ -1620,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{
@@ -2405,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 4abd397..f13a638 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -17,8 +17,12 @@
 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;
+import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.systemBars;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
@@ -30,6 +34,8 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -43,6 +49,7 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
@@ -66,6 +73,7 @@
 import android.util.AndroidRuntimeException;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Pair;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
@@ -127,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;
@@ -307,6 +320,8 @@
     /** @see ViewRootImpl#mActivityConfigCallback */
     private ActivityConfigCallback mActivityConfigCallback;
 
+    private OnContentApplyWindowInsetsListener mPendingOnContentApplyWindowInsetsListener;
+
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService("window"));
@@ -318,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;
     }
 
     /**
@@ -2092,6 +2109,34 @@
     /** Notify when decor view is attached to window and {@link ViewRootImpl} is available. */
     void onViewRootImplSet(ViewRootImpl viewRoot) {
         viewRoot.setActivityConfigCallback(mActivityConfigCallback);
+        if (mPendingOnContentApplyWindowInsetsListener != null) {
+            viewRoot.setOnContentApplyWindowInsetsListener(
+                    mPendingOnContentApplyWindowInsetsListener);
+            mPendingOnContentApplyWindowInsetsListener = null;
+        } else {
+            viewRoot.setOnContentApplyWindowInsetsListener(
+                    createDefaultContentWindowInsetsListener());
+        }
+    }
+
+    private OnContentApplyWindowInsetsListener createDefaultContentWindowInsetsListener() {
+        return insets -> {
+            if ((getDecorView().getWindowSystemUiVisibility() & SYSTEM_UI_LAYOUT_FLAGS) != 0) {
+                return new Pair<>(Insets.NONE, insets);
+            }
+
+            boolean includeIme = (getAttributes().softInputMode & SOFT_INPUT_MASK_ADJUST)
+                    == SOFT_INPUT_ADJUST_RESIZE;
+            Insets insetsToApply;
+            if (ViewRootImpl.sNewInsetsMode == 0) {
+                insetsToApply = insets.getSystemWindowInsets();
+            } else {
+                insetsToApply = insets.getInsets(systemBars() | (includeIme ? ime() : 0));
+            }
+            insets = insets.inset(insetsToApply);
+            return new Pair<>(insetsToApply,
+                    insets.inset(insetsToApply).consumeSystemWindowInsets());
+        };
     }
 
     static private final String FOCUSED_ID_TAG = "android:focusedViewId";
@@ -2344,6 +2389,8 @@
             setFlags(0, flagsToUpdate);
         } else {
             setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
+            getAttributes().setFitInsetsSides(0);
+            getAttributes().setFitInsetsTypes(0);
         }
 
         if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
@@ -2656,7 +2703,7 @@
             mContentParent = generateLayout(mDecor);
 
             // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
-            mDecor.makeOptionalFitsSystemWindows();
+            mDecor.makeFrameworkOptionalFitsSystemWindows();
 
             final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                     R.id.decor_content_parent);
@@ -3853,4 +3900,19 @@
     public List<Rect> getSystemGestureExclusionRects() {
         return getViewRootImpl().getRootSystemGestureExclusionRects();
     }
+
+    @Override
+    public void setOnContentApplyWindowInsetsListener(OnContentApplyWindowInsetsListener listener) {
+        ViewRootImpl impl = getViewRootImpl();
+        if (impl != null) {
+            impl.setOnContentApplyWindowInsetsListener(listener);
+        } else {
+            mPendingOnContentApplyWindowInsetsListener = listener;
+        }
+    }
+
+    @Override
+    public void resetOnContentApplyWindowInsetsListener() {
+        setOnContentApplyWindowInsetsListener(createDefaultContentWindowInsetsListener());
+    }
 }
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/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..eb7d432 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -475,8 +475,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,
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_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_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index e266fe6..0156e23 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -307,6 +307,43 @@
     return kAudioStatusError;
 }
 
+static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
+                                           jobjectArray deviceAddresses,
+                                           Vector<AudioDeviceTypeAddr> &audioDeviceTypeAddrVector) {
+    if (deviceTypes == nullptr || deviceAddresses == nullptr) {
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+    jsize deviceCount = env->GetArrayLength(deviceTypes);
+    if (deviceCount == 0 || deviceCount != env->GetArrayLength(deviceAddresses)) {
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+    // retrieve all device types
+    std::vector<audio_devices_t> deviceTypesVector;
+    jint *typesPtr = nullptr;
+    typesPtr = env->GetIntArrayElements(deviceTypes, 0);
+    if (typesPtr == nullptr) {
+        return (jint)AUDIO_JAVA_BAD_VALUE;
+    }
+    for (jint i = 0; i < deviceCount; i++) {
+        deviceTypesVector.push_back((audio_devices_t)typesPtr[i]);
+    }
+    // check each address is a string and add device type/address to list
+    jclass stringClass = FindClassOrDie(env, "java/lang/String");
+    for (jint i = 0; i < deviceCount; i++) {
+        jobject addrJobj = env->GetObjectArrayElement(deviceAddresses, i);
+        if (!env->IsInstanceOf(addrJobj, stringClass)) {
+            return (jint)AUDIO_JAVA_BAD_VALUE;
+        }
+        const char *address = env->GetStringUTFChars((jstring)addrJobj, NULL);
+        AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
+        audioDeviceTypeAddrVector.add(dev);
+        env->ReleaseStringUTFChars((jstring)addrJobj, address);
+    }
+    env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
+
+    return (jint)NO_ERROR;
+}
+
 static jint
 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
 {
@@ -1905,6 +1942,10 @@
             nCriterion.mValue.mUid = env->GetIntField(jCriterion,
                     gAudioMixMatchCriterionFields.mIntProp);
             break;
+        case RULE_MATCH_USERID:
+            nCriterion.mValue.mUserId =
+                    env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp);
+            break;
         case RULE_MATCH_ATTRIBUTE_USAGE:
         case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
             jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
@@ -1990,39 +2031,11 @@
 
 static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobject clazz,
         jint uid, jintArray deviceTypes, jobjectArray deviceAddresses) {
-    if (deviceTypes == nullptr || deviceAddresses == nullptr) {
-        return (jint) AUDIO_JAVA_BAD_VALUE;
-    }
-    jsize nb = env->GetArrayLength(deviceTypes);
-    if (nb == 0 || nb != env->GetArrayLength(deviceAddresses)) {
-        return (jint) AUDIO_JAVA_BAD_VALUE;
-    }
-    // retrieve all device types
-    std::vector<audio_devices_t> deviceTypesVector;
-    jint* typesPtr = nullptr;
-    typesPtr = env->GetIntArrayElements(deviceTypes, 0);
-    if (typesPtr == nullptr) {
-        return (jint) AUDIO_JAVA_BAD_VALUE;
-    }
-    for (jint i = 0; i < nb; i++) {
-        deviceTypesVector.push_back((audio_devices_t) typesPtr[i]);
-    }
-
-    // check each address is a string and add device type/address to list for device affinity
     Vector<AudioDeviceTypeAddr> deviceVector;
-    jclass stringClass = FindClassOrDie(env, "java/lang/String");
-    for (jint i = 0; i < nb; i++) {
-        jobject addrJobj = env->GetObjectArrayElement(deviceAddresses, i);
-        if (!env->IsInstanceOf(addrJobj, stringClass)) {
-            return (jint) AUDIO_JAVA_BAD_VALUE;
-        }
-        const char* address = env->GetStringUTFChars((jstring) addrJobj, NULL);
-        AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
-        deviceVector.add(dev);
-        env->ReleaseStringUTFChars((jstring) addrJobj, address);
+    jint results = getVectorOfAudioDeviceTypeAddr(env, deviceTypes, deviceAddresses, deviceVector);
+    if (results != NO_ERROR) {
+        return results;
     }
-    env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
-
     status_t status = AudioSystem::setUidDeviceAffinities((uid_t) uid, deviceVector);
     return (jint) nativeToJavaStatus(status);
 }
@@ -2033,6 +2046,23 @@
     return (jint) nativeToJavaStatus(status);
 }
 
+static jint android_media_AudioSystem_setUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
+                                                                jint userId, jintArray deviceTypes,
+                                                                jobjectArray deviceAddresses) {
+    Vector<AudioDeviceTypeAddr> deviceVector;
+    jint results = getVectorOfAudioDeviceTypeAddr(env, deviceTypes, deviceAddresses, deviceVector);
+    if (results != NO_ERROR) {
+        return results;
+    }
+    status_t status = AudioSystem::setUserIdDeviceAffinities((int)userId, deviceVector);
+    return (jint)nativeToJavaStatus(status);
+}
+
+static jint android_media_AudioSystem_removeUserIdDeviceAffinities(JNIEnv *env, jobject clazz,
+                                                                   jint userId) {
+    status_t status = AudioSystem::removeUserIdDeviceAffinities((int)userId);
+    return (jint)nativeToJavaStatus(status);
+}
 
 static jint
 android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
@@ -2463,7 +2493,9 @@
     {"setPreferredDeviceForStrategy", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setPreferredDeviceForStrategy},
     {"removePreferredDeviceForStrategy", "(I)I", (void *)android_media_AudioSystem_removePreferredDeviceForStrategy},
     {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getPreferredDeviceForStrategy},
-    {"getDevicesForAttributes", "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getDevicesForAttributes}
+    {"getDevicesForAttributes", "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAddress;)I", (void *)android_media_AudioSystem_getDevicesForAttributes},
+    {"setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I", (void *)android_media_AudioSystem_setUserIdDeviceAffinities},
+    {"removeUserIdDeviceAffinities", "(I)I", (void *)android_media_AudioSystem_removeUserIdDeviceAffinities}
 };
 
 static const JNINativeMethod gEventHandlerMethods[] = {
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_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..60f2fc8 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -589,7 +589,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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4f2dff4..fdfac97 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" />
@@ -1528,6 +1529,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
@@ -1616,6 +1625,7 @@
 
     <!-- Allows applications to request network
          recommendations and scores from the NetworkScoreService.
+         @SystemApi
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
         android:protectionLevel="signature|setup" />
@@ -2253,6 +2263,9 @@
     <eat-comment />
 
     <!-- @SystemApi @TestApi Allows an application to write to internal media storage
+         @deprecated This permission is no longer honored in the system and no longer adds
+         the media_rw gid as a supplementary gid to the holder. Use the
+         android.permission.MANAGE_EXTERNAL_STORAGE instead.
          @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
         android:protectionLevel="signature|privileged" />
@@ -2531,6 +2544,14 @@
                 android:description="@string/permdesc_useDataInBackground"
                 android:protectionLevel="normal" />
 
+    <!-- Allows a companion app to associate to Wi-Fi.
+         <p>Only for use by a single pre-approved app.
+         @hide
+         @SystemApi
+    -->
+    <permission android:name="android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS"
+                android:protectionLevel="signature|privileged" />
+
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
@@ -2709,6 +2730,11 @@
     <permission android:name="android.permission.READ_DEVICE_CONFIG"
         android:protectionLevel="signature|preinstalled" />
 
+    <!-- @SystemApi @hide Allows an application to monitor config settings access.
+    <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
+        android:protectionLevel="signature"/>
+
     <!-- @SystemApi @TestApi Allows an application to call
         {@link android.app.ActivityManager#forceStopPackage}.
         @hide -->
@@ -3715,6 +3741,13 @@
     <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to control the lights on the device.
+         @hide
+         @SystemApi
+         @TestApi -->
+    <permission android:name="android.permission.CONTROL_DEVICE_LIGHTS"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Allows an application to control the color saturation of the display.
          @hide
          @SystemApi -->
@@ -4274,6 +4307,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" />
@@ -5022,12 +5060,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/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 0c45e45..4e8a41f 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -61,10 +61,33 @@
         android:layout_height="wrap_content"
         android:visibility="gone" />
 
-    <com.android.internal.widget.ViewPager
-        android:id="@+id/profile_pager"
+    <TabHost
+        android:id="@+id/profile_tabhost"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="?attr/colorBackgroundFloating">
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            </TabWidget>
+            <FrameLayout
+                android:id="@android:id/tabcontent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <com.android.internal.app.ResolverViewPager
+                    android:id="@+id/profile_pager"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"/>
+            </FrameLayout>
+        </LinearLayout>
+    </TabHost>
 
     <TextView android:id="@+id/empty"
               android:layout_width="match_parent"
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index c5d8912..757cd53 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -70,14 +70,44 @@
         android:background="?attr/colorBackgroundFloating"
         android:foreground="?attr/dividerVertical" />
 
-    <com.android.internal.app.WrapHeightViewPager
-        android:id="@+id/profile_pager"
+    <FrameLayout
+        android:id="@+id/stub"
+        android:visibility="gone"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:divider="?attr/dividerVertical"
-        android:footerDividersEnabled="false"
-        android:headerDividersEnabled="false"
-        android:dividerHeight="1dp"/>
+        android:background="?attr/colorBackgroundFloating"/>
+
+    <TabHost
+        android:id="@+id/profile_tabhost"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="?attr/colorBackgroundFloating">
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            </TabWidget>
+            <FrameLayout
+                android:id="@android:id/tabcontent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <com.android.internal.app.ResolverViewPager
+                    android:id="@+id/profile_pager"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:divider="?attr/dividerVertical"
+                    android:footerDividersEnabled="false"
+                    android:headerDividersEnabled="false"
+                    android:dividerHeight="1dp"/>
+            </FrameLayout>
+        </LinearLayout>
+    </TabHost>
 
     <View
         android:layout_alwaysShow="true"
diff --git a/core/res/res/layout/resolver_list_per_profile.xml b/core/res/res/layout/resolver_list_per_profile.xml
index 68b9917..6d8d348 100644
--- a/core/res/res/layout/resolver_list_per_profile.xml
+++ b/core/res/res/layout/resolver_list_per_profile.xml
@@ -25,7 +25,7 @@
     android:nestedScrollingEnabled="true"
     android:scrollbarStyle="outsideOverlay"
     android:scrollIndicators="top|bottom"
-    android:divider="?attr/dividerVertical"
+    android:divider="@null"
     android:footerDividersEnabled="false"
     android:headerDividersEnabled="false"
-    android:dividerHeight="1dp" />
\ No newline at end of file
+    android:dividerHeight="0dp" />
\ No newline at end of file
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 5b3d929..b546738 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -151,14 +151,46 @@
         android:background="?attr/colorBackgroundFloating"
         android:foreground="?attr/dividerVertical" />
 
-    <com.android.internal.app.WrapHeightViewPager
-        android:id="@+id/profile_pager"
+    <FrameLayout
+        android:id="@+id/stub"
+        android:visibility="gone"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:dividerHeight="1dp"
-        android:divider="?attr/dividerVertical"
-        android:footerDividersEnabled="false"
-        android:headerDividersEnabled="false"/>
+        android:background="?attr/colorBackgroundFloating"/>
+
+    <TabHost
+        android:id="@+id/profile_tabhost"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="?attr/colorBackgroundFloating">
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone">
+            </TabWidget>
+            <FrameLayout
+                android:id="@android:id/tabcontent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <com.android.internal.app.ResolverViewPager
+                    android:id="@+id/profile_pager"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:dividerHeight="1dp"
+                    android:divider="?attr/dividerVertical"
+                    android:footerDividersEnabled="false"
+                    android:headerDividersEnabled="false"/>
+            </FrameLayout>
+        </LinearLayout>
+    </TabHost>
+
     <View
         android:layout_alwaysShow="true"
         android:layout_width="match_parent"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index be0e588..de8f55b 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..ec9abfe 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..0d70a11 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>
@@ -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>
@@ -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>
@@ -1703,7 +1704,6 @@
     <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>
@@ -1978,13 +1978,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 +2097,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 +2119,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 +2141,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..ad11a37 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..a535f1f 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..249e5af 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>
@@ -1634,7 +1638,6 @@
     <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 +1882,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 +2020,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 +2039,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..dc4c56e 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..30b7d30 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..d85b5d6 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..c8c65bb 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>
@@ -1636,7 +1640,6 @@
     <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 +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. 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 +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 ć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 +2041,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..42bebe1 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..2c16291 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>
@@ -1656,7 +1660,6 @@
     <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 +1914,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 +2053,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 +2073,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..f86db77 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..d6a9a01 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..67285e9 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..ed31c22 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..6ae46b4 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..ed31c22 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..ed31c22 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..07cb6c7 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..6f83551 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..737a83b 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..021985f 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..8ecdd07 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..9c3403b 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..a42b87d 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..47f4184 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..7898e79 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..e7498b9 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..b52d99ef 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8105441..3140c76 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..feb29e2 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>
@@ -1634,7 +1638,6 @@
     <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 +1882,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 +2020,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 +2039,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..20d38ae 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..d13b9ea 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..c2a0817 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..c596c12 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..1144995 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..bce62ab 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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="two"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> קבצים</item>
@@ -2078,5 +2074,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-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e7f5e85..1ef4a13 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..41b2388 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..3ea4d351 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..4f7c0fe 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>
@@ -1617,7 +1618,6 @@
     <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 +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>
@@ -1969,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>
@@ -1995,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>
@@ -2012,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-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 50b1bba..9efa857 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 7e12490..90fa0fa 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..07a6e3f 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>
@@ -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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..05f9698 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..4f48685 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>
@@ -1656,7 +1660,6 @@
     <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 +1914,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 +2053,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 +2073,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..ae9abc6 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>
@@ -1637,7 +1638,6 @@
     <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 +1882,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 +1998,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 +2020,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 +2039,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..f1e5406 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>
@@ -1614,7 +1618,6 @@
     <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 +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>
@@ -1986,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>
@@ -2003,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-ml/strings.xml b/core/res/res/values-ml/strings.xml
index b0bbb67..f0cc48c 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 205df27..3be3a04 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b27e1c9..a2bf479 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..f7626db 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..556837e 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..6f3b6c2 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..ebbf50b 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>
@@ -1621,7 +1622,6 @@
     <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 +1856,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 +1971,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 +1993,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>
@@ -2016,5 +2012,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-nl/strings.xml b/core/res/res/values-nl/strings.xml
index dece9ae..0635c21 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..03a7ea3 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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..b2cca4d 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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..94fd851 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..72a3ce9 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..4f45517 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..72a3ce9 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..d7cdade 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>
@@ -1637,7 +1638,6 @@
     <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 +1882,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 +1998,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 +2020,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 +2039,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..91b7ca6 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..601f9b9 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>
@@ -1617,7 +1618,6 @@
     <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 +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>
@@ -1969,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>
@@ -1995,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>
@@ -2012,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-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f48368f..fb81855 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..9405fb2 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..fe167da 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..564612c 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>
@@ -1634,7 +1638,6 @@
     <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 +1882,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 +2020,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 +2039,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..4332352 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..d1bff3f5 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..5444f36 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..f9f6479 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-th/strings.xml b/core/res/res/values-th/strings.xml
index 11aa407..7796b03 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..d15bcd7 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..e5559c5 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..7c06892 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>
@@ -1659,7 +1660,6 @@
     <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 +1914,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 +2031,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 +2053,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 +2073,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..1b00720 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-uz/strings.xml b/core/res/res/values-uz/strings.xml
index c837414..1193d27 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..7cfd870 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..5d7ad5a 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2006,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-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2929869..361eb4c 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..2bcae59 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>
@@ -1615,7 +1616,6 @@
     <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 +1850,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 +1965,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 +1987,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 +2005,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..e96696e 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>
@@ -1612,7 +1616,6 @@
     <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 +1850,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 +1987,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 +2005,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..c9c47b9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9197,4 +9197,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/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0895edc..cfed805 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2260,6 +2260,55 @@
         <attr name="name" />
     </declare-styleable>
 
+    <!-- The <code>processes</code> tag specifies the processes the application will run code in
+         and optionally characteristics of those processes.  This tag is optional; if not
+         specified, components will simply run in the processes they specify.  If supplied,
+         they can only specify processes that are enumerated here, and if they don't this
+         will be treated as a corrupt apk and result in an install failure.
+
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestApplication application} tag. -->
+    <declare-styleable name="AndroidManifestProcesses" parent="AndroidManifestApplication">
+    </declare-styleable>
+
+    <!-- The <code>process</code> tag enumerates one of the available processes under its
+         containing <code>processes</code> tag.
+
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestProcesses processes} tag. -->
+    <declare-styleable name="AndroidManifestProcess" parent="AndroidManifestProcesses">
+        <!-- Required name of the process that is allowed -->
+        <attr name="process" />
+    </declare-styleable>
+
+    <!-- The <code>deny-permission</code> tag specifies that a permission is to be denied
+         for a particular process (if specified under the
+         {@link #AndroidManifestProcess process} tag) or by default for all
+         processes {if specified under the
+         @link #AndroidManifestProcesses processes} tag).
+
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestProcesses processes} and
+         {@link #AndroidManifestProcess process} tags. -->
+    <declare-styleable name="AndroidManifestDenyPermission"
+            parent="AndroidManifestProcesses">
+        <!-- Required name of the permission that is to be denied -->
+        <attr name="name" />
+    </declare-styleable>
+
+    <!-- The <code>allow-permission</code> tag specifies that a permission is to be allowed
+         for a particular process, when it was previously denied for all processes through
+         {@link #AndroidManifestDenyPermission deny-permission}
+
+         <p>This appears as a child tag of the
+         {@link #AndroidManifestProcesses processes} and
+         {@link #AndroidManifestProcess process} tags. -->
+    <declare-styleable name="AndroidManifestAllowPermission"
+            parent="AndroidManifestProcesses">
+        <!-- Required name of the permission that is to be allowed. -->
+        <attr name="name" />
+    </declare-styleable>
+
     <!-- The <code>provider</code> tag declares a
          {@link android.content.ContentProvider} class that is available
          as part of the package's application components, supplying structured
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 1dcd389..731e2ec 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -224,4 +224,6 @@
 
     <!-- Resolver/Chooser -->
     <color name="resolver_text_color_secondary_dark">#ffC4C6C6</color>
+    <color name="resolver_tabs_active_color">#FF1A73E8</color>
+    <color name="resolver_tabs_inactive_color">#FF80868B</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7fd444a..dadb9241 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1628,29 +1628,21 @@
          config_timeZoneRulesUpdateTrackingEnabled are true.] -->
     <integer name="config_timeZoneRulesCheckRetryCount">5</integer>
 
-    <!-- Whether to enable network location overlay which allows network
-         location provider to be replaced by an app at run-time. When disabled,
-         only the config_networkLocationProviderPackageName package will be
-         searched for network location provider, otherwise packages whose
-         signature matches the signatures of config_locationProviderPackageNames
-         will be searched, and the service with the highest version number will
-         be picked. Anyone who wants to disable the overlay mechanism can set it
-         to false.
-         -->
+    <!-- Whether to enable network location overlay which allows network location provider to be
+         replaced by an app at run-time. When disabled, only the
+         config_networkLocationProviderPackageName package will be searched for network location
+         provider, otherwise any system package is eligible. Anyone who wants to disable the overlay
+         mechanism can set it to false. -->
     <bool name="config_enableNetworkLocationOverlay" translatable="false">true</bool>
     <!-- Package name providing network location support. Used only when
          config_enableNetworkLocationOverlay is false. -->
     <string name="config_networkLocationProviderPackageName" translatable="false">@null</string>
 
-    <!-- Whether to enable fused location provider overlay which allows fused
-         location provider to be replaced by an app at run-time. When disabled,
-         only the config_fusedLocationProviderPackageName package will be
-         searched for fused location provider, otherwise packages whose
-         signature matches the signatures of config_locationProviderPackageNames
-         will be searched, and the service with the highest version number will
-         be picked. Anyone who wants to disable the overlay mechanism can set it
-         to false.
-         -->
+    <!-- Whether to enable fused location provider overlay which allows fused location provider to
+         be replaced by an app at run-time. When disabled, only the
+         config_fusedLocationProviderPackageName package will be searched for fused location
+         provider, otherwise any system package is eligible. Anyone who wants to disable the overlay
+         mechanism can set it to false. -->
     <bool name="config_enableFusedLocationOverlay" translatable="false">true</bool>
     <!-- Package name providing fused location support. Used only when
          config_enableFusedLocationOverlay is false. -->
@@ -1669,25 +1661,10 @@
      -->
     <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false"></string>
 
-    <!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
-         replaced by an app at run-time. When disabled, only the
-         config_hardwareFlpPackageName package will be searched for Hardware Flp,
-         otherwise packages whose signature matches the signatures of
-         config_locationProviderPackageNames will be searched, and the service
-         with the highest version number will be picked. Anyone who wants to
-         disable the overlay mechanism can set it to false.
-         -->
-    <bool name="config_enableHardwareFlpOverlay" translatable="false">true</bool>
-    <!-- Package name providing Hardware Flp. Used only when
-         config_enableHardwareFlpOverlay is false. -->
-    <string name="config_hardwareFlpPackageName" translatable="false">com.android.location.fused</string>
-
     <!-- Whether to enable geocoder overlay which allows geocoder to be replaced
          by an app at run-time. When disabled, only the
          config_geocoderProviderPackageName package will be searched for
-         geocoder, otherwise packages whose signature matches the signatures of
-         config_locationProviderPackageNames will be searched, and the service
-         with the highest version number will be picked. Anyone who wants to
+         geocoder, otherwise any system package is eligible. Anyone who wants to
          disable the overlay mechanism can set it to false.
          -->
     <bool name="config_enableGeocoderOverlay" translatable="false">true</bool>
@@ -1698,9 +1675,7 @@
     <!-- Whether to enable geofence overlay which allows geofence to be replaced
          by an app at run-time. When disabled, only the
          config_geofenceProviderPackageName package will be searched for
-         geofence implementation, otherwise packages whose signature matches the
-         signatures of config_locationProviderPackageNames will be searched, and
-         the service with the highest version number will be picked. Anyone who
+         geofence implementation, otherwise any system package is eligible. Anyone who
          wants to disable the overlay mechanism can set it to false.
          -->
     <bool name="config_enableGeofenceOverlay" translatable="false">true</bool>
@@ -1711,9 +1686,7 @@
     <!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware
          Activity-Recognition to be replaced by an app at run-time. When disabled, only the
          config_activityRecognitionHardwarePackageName package will be searched for
-         its implementation, otherwise packages whose signature matches the
-         signatures of config_locationProviderPackageNames will be searched, and
-         the service with the highest version number will be picked. Anyone who
+         its implementation, otherwise any system package is eligible. Anyone who
          wants to disable the overlay mechanism can set it to false.
          -->
     <bool name="config_enableActivityRecognitionHardwareOverlay" translatable="false">true</bool>
@@ -1721,19 +1694,8 @@
          config_enableActivityRecognitionHardwareOverlay is false. -->
     <string name="config_activityRecognitionHardwarePackageName" translatable="false">@null</string>
 
-    <!-- Package name(s) containing location provider support.
-         These packages can contain services implementing location providers,
-         such as the Geocode Provider, Network Location Provider, and
-         Fused Location Provider. They will each be searched for
-         service components implementing these providers.
-         It is strongly recommended that the packages explicitly named
-         below are on the system image, so that they will not map to
-         a 3rd party application.
-         The location framework also has support for installation
-         of new location providers at run-time. The new package does not
-         have to be explicitly listed here, however it must have a signature
-         that matches the signature of at least one package on this list.
-         -->
+    <!-- Package name(s) containing location provider support. These packages will be auto-granted
+         several permissions by the system, and should be system packages. -->
     <string-array name="config_locationProviderPackageNames" translatable="false">
         <!-- The standard AOSP fused location provider -->
         <item>com.android.location.fused</item>
@@ -2723,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>
 
@@ -4211,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
@@ -4326,6 +4293,13 @@
          generation). -->
     <bool name="config_customBugreport">false</bool>
 
+    <!-- Names of packages that should not be suspended when personal use is blocked by policy. -->
+    <string-array name="config_packagesExemptFromSuspension" translatable="false">
+        <!-- Add packages here, example: -->
+        <!-- <item>com.android.settings</item> -->
+    </string-array>
+
+
     <!-- Class name of the custom country detector to be used. -->
     <string name="config_customCountryDetector" translatable="false">com.android.server.location.ComprehensiveCountryDetector</string>
 
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 bed418d..11cc365 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -425,6 +425,12 @@
     <!-- A toast message displayed when printing is attempted but disabled by policy. -->
     <string name="printing_disabled_by">Printing disabled by <xliff:g id="owner_app">%s</xliff:g>.</string>
 
+    <!-- Content title for a notification that personal apps are suspended [CHAR LIMIT=NONE] -->
+    <string name="personal_apps_suspended_notification_title">Personal apps have been suspended by an admin</string>
+
+    <!-- Message for a notification about personal apps suspension when work profile is off. [CHAR LIMIT=NONE] -->
+    <string name="personal_apps_suspended_notification_text">Tap here to check policy compliance.</string>
+
     <!-- Display name for any time a piece of data refers to the owner of the phone. For example, this could be used in place of the phone's phone number. -->
     <string name="me">Me</string>
 
@@ -4339,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">
@@ -4917,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>
@@ -4925,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] -->
@@ -5312,11 +5316,16 @@
     <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>
 
     <!-- Text to tell the user that a package has been forced by themselves in the RESTRICTED bucket. [CHAR LIMIT=NONE] -->
     <string name="as_app_forced_to_restricted_bucket">
         <xliff:g id="package_name" example="com.android.example">%1$s</xliff:g> has been put into the RESTRICTED bucket</string>
+
+    <!-- ResolverActivity - profile tabs -->
+    <string name="resolver_personal_tab">Personal</string>
+    <string name="resolver_work_tab">Work</string>
 </resources>
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 357b1f0..d238485 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -249,6 +249,9 @@
   <java-symbol type="id" name="app_ops" />
   <java-symbol type="id" name="profile_pager" />
   <java-symbol type="id" name="content_preview_container" />
+  <java-symbol type="id" name="profile_tabhost" />
+  <java-symbol type="id" name="tabs" />
+  <java-symbol type="id" name="tabcontent" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -357,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" />
@@ -1209,6 +1213,8 @@
   <java-symbol type="string" name="device_ownership_relinquished" />
   <java-symbol type="string" name="network_logging_notification_title" />
   <java-symbol type="string" name="network_logging_notification_text" />
+  <java-symbol type="string" name="personal_apps_suspended_notification_title" />
+  <java-symbol type="string" name="personal_apps_suspended_notification_text" />
   <java-symbol type="string" name="factory_reset_warning" />
   <java-symbol type="string" name="factory_reset_message" />
   <java-symbol type="string" name="lockscreen_transport_play_description" />
@@ -1235,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" />
@@ -1869,7 +1875,6 @@
   <java-symbol type="bool" name="config_dozeAfterScreenOffByDefault" />
   <java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" />
   <java-symbol type="bool" name="config_enableFusedLocationOverlay" />
-  <java-symbol type="bool" name="config_enableHardwareFlpOverlay" />
   <java-symbol type="bool" name="config_enableGeocoderOverlay" />
   <java-symbol type="bool" name="config_enableGeofenceOverlay" />
   <java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
@@ -2019,7 +2024,6 @@
   <java-symbol type="string" name="config_datause_iface" />
   <java-symbol type="string" name="config_activityRecognitionHardwarePackageName" />
   <java-symbol type="string" name="config_fusedLocationProviderPackageName" />
-  <java-symbol type="string" name="config_hardwareFlpPackageName" />
   <java-symbol type="string" name="config_geocoderProviderPackageName" />
   <java-symbol type="string" name="config_geofenceProviderPackageName" />
   <java-symbol type="string" name="config_networkLocationProviderPackageName" />
@@ -3035,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" />
 
@@ -3800,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" />
 
@@ -3822,6 +3825,9 @@
   <java-symbol type="dimen" name="waterfall_display_right_edge_size" />
   <java-symbol type="dimen" name="waterfall_display_bottom_edge_size" />
 
+  <!-- For device policy -->
+  <java-symbol type="array" name="config_packagesExemptFromSuspension" />
+
   <!-- Accessibility take screenshot -->
   <java-symbol type="string" name="capability_desc_canTakeScreenshot" />
   <java-symbol type="string" name="capability_title_canTakeScreenshot" />
@@ -3833,4 +3839,14 @@
 
   <java-symbol type="array" name="config_defaultImperceptibleKillingExemptionPkgs" />
   <java-symbol type="array" name="config_defaultImperceptibleKillingExemptionProcStates" />
+
+  <!-- Intent resolver and share sheet -->
+  <java-symbol type="color" name="resolver_tabs_active_color" />
+  <java-symbol type="color" name="resolver_tabs_inactive_color" />
+  <java-symbol type="string" name="resolver_personal_tab" />
+  <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/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/SnippetTest.java b/core/tests/coretests/src/android/app/appsearch/SnippetTest.java
new file mode 100644
index 0000000..3103708
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/SnippetTest.java
@@ -0,0 +1,200 @@
+/*
+ * 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.app.appsearch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.android.icing.proto.DocumentProto;
+import com.google.android.icing.proto.PropertyProto;
+import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SnippetMatchProto;
+import com.google.android.icing.proto.SnippetProto;
+
+import org.junit.Test;
+
+@SmallTest
+public class SnippetTest {
+
+    // TODO(sidchhabra): Add tests for Double and Long Snippets.
+    @Test
+    public void testSingleStringSnippet() {
+
+        final String propertyKeyString = "content";
+        final String propertyValueString = "A commonly used fake word is foo.\n"
+                + "   Another nonsense word that’s used a lot\n"
+                + "   is bar.\n";
+        final String uri = "uri1";
+        final String schemaType = "schema1";
+        final String searchWord = "foo";
+        final String exactMatch = "foo";
+        final String window = "is foo";
+
+        // Building the SearchResult received from query.
+        PropertyProto property = PropertyProto.newBuilder()
+                .setName(propertyKeyString)
+                .addStringValues(propertyValueString)
+                .build();
+        DocumentProto documentProto = DocumentProto.newBuilder()
+                .setUri(uri)
+                .setSchema(schemaType)
+                .addProperties(property)
+                .build();
+        SnippetProto snippetProto = SnippetProto.newBuilder()
+                .addEntries(SnippetProto.EntryProto.newBuilder()
+                        .setPropertyName(propertyKeyString)
+                        .addSnippetMatches(SnippetMatchProto.newBuilder()
+                                .setValuesIndex(0)
+                                .setExactMatchPosition(29)
+                                .setExactMatchBytes(3)
+                                .setWindowPosition(26)
+                                .setWindowBytes(6)
+                                .build())
+                        .build())
+                .build();
+        SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
+                .setDocument(documentProto)
+                .setSnippet(snippetProto)
+                .build();
+        SearchResultProto searchResultProto = SearchResultProto.newBuilder()
+                .addResults(resultProto)
+                .build();
+        SearchResults searchResults = new SearchResults(searchResultProto);
+
+        // Making ResultReader and getting Snippet values.
+        while (searchResults.hasNext()) {
+            SearchResults.Result result = searchResults.next();
+            MatchInfo match = result.getMatchInfo().get(0);
+            assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
+            assertThat(match.getFullText()).isEqualTo(propertyValueString);
+            assertThat(match.getExactMatch()).isEqualTo(exactMatch);
+            assertThat(match.getSnippet()).isEqualTo(window);
+        }
+    }
+
+    // TODO(sidchhabra): Add tests for Double and Long Snippets.
+    @Test
+    public void testNoSnippets() {
+
+        final String propertyKeyString = "content";
+        final String propertyValueString = "A commonly used fake word is foo.\n"
+                + "   Another nonsense word that’s used a lot\n"
+                + "   is bar.\n";
+        final String uri = "uri1";
+        final String schemaType = "schema1";
+        final String searchWord = "foo";
+        final String exactMatch = "foo";
+        final String window = "is foo";
+
+        // Building the SearchResult received from query.
+        PropertyProto property = PropertyProto.newBuilder()
+                .setName(propertyKeyString)
+                .addStringValues(propertyValueString)
+                .build();
+        DocumentProto documentProto = DocumentProto.newBuilder()
+                .setUri(uri)
+                .setSchema(schemaType)
+                .addProperties(property)
+                .build();
+        SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
+                .setDocument(documentProto)
+                .build();
+        SearchResultProto searchResultProto = SearchResultProto.newBuilder()
+                .addResults(resultProto)
+                .build();
+        SearchResults searchResults = new SearchResults(searchResultProto);
+
+        while (searchResults.hasNext()) {
+            SearchResults.Result result = searchResults.next();
+            assertThat(result.getMatchInfo()).isEqualTo(null);
+        }
+    }
+
+    @Test
+    public void testMultipleStringSnippet() {
+        final String searchWord = "Test";
+
+        // Building the SearchResult received from query.
+        PropertyProto property1 = PropertyProto.newBuilder()
+                .setName("sender.name")
+                .addStringValues("Test Name Jr.")
+                .build();
+        PropertyProto property2 = PropertyProto.newBuilder()
+                .setName("sender.email")
+                .addStringValues("TestNameJr@gmail.com")
+                .build();
+        DocumentProto documentProto = DocumentProto.newBuilder()
+                .setUri("uri1")
+                .setSchema("schema1")
+                .addProperties(property1)
+                .addProperties(property2)
+                .build();
+        SnippetProto snippetProto = SnippetProto.newBuilder()
+                .addEntries(
+                        SnippetProto.EntryProto.newBuilder()
+                                .setPropertyName("sender.name")
+                                .addSnippetMatches(
+                                        SnippetMatchProto.newBuilder()
+                                                .setValuesIndex(0)
+                                                .setExactMatchPosition(0)
+                                                .setExactMatchBytes(4)
+                                                .setWindowPosition(0)
+                                                .setWindowBytes(9)
+                                                .build())
+                                .build())
+                .addEntries(
+                        SnippetProto.EntryProto.newBuilder()
+                                .setPropertyName("sender.email")
+                                .addSnippetMatches(
+                                        SnippetMatchProto.newBuilder()
+                                                .setValuesIndex(0)
+                                                .setExactMatchPosition(0)
+                                                .setExactMatchBytes(20)
+                                                .setWindowPosition(0)
+                                                .setWindowBytes(20)
+                                                .build())
+                                .build()
+                )
+                .build();
+        SearchResultProto.ResultProto resultProto = SearchResultProto.ResultProto.newBuilder()
+                .setDocument(documentProto)
+                .setSnippet(snippetProto)
+                .build();
+        SearchResultProto searchResultProto = SearchResultProto.newBuilder()
+                .addResults(resultProto)
+                .build();
+        SearchResults searchResults = new SearchResults(searchResultProto);
+
+        // Making ResultReader and getting Snippet values.
+        while (searchResults.hasNext()) {
+            SearchResults.Result result = searchResults.next();
+
+            MatchInfo match1 = result.getMatchInfo().get(0);
+            assertThat(match1.getPropertyPath()).isEqualTo("sender.name");
+            assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
+            assertThat(match1.getExactMatch()).isEqualTo("Test");
+            assertThat(match1.getSnippet()).isEqualTo("Test Name");
+
+            MatchInfo match2 = result.getMatchInfo().get(1);
+            assertThat(match2.getPropertyPath()).isEqualTo("sender.email");
+            assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com");
+            assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com");
+            assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com");
+        }
+    }
+}
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..c0d9be5 100644
--- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -18,12 +18,9 @@
 
 import static android.content.integrity.TestUtils.assertExpectException;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.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,7 +127,8 @@
         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
@@ -73,12 +145,14 @@
     }
 
     @Test
-    public void testInvalidAtomicFormula_intValue() {
+    public void testInvalidAtomicFormula_longValue() {
         assertExpectException(
                 IllegalArgumentException.class,
                 /* expectedExceptionMessageRegex */
-                String.format("Key PACKAGE_NAME cannot be used with IntAtomicFormula"),
-                () -> new IntAtomicFormula(AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+                String.format("Key PACKAGE_NAME cannot be used with LongAtomicFormula"),
+                () ->
+                        new AtomicFormula.LongAtomicFormula(
+                                AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
     }
 
     @Test
@@ -91,148 +165,6 @@
     }
 
     @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));
-    }
-
-    @Test
     public void testParcelUnparcel_string() {
         StringAtomicFormula formula =
                 new StringAtomicFormula(
@@ -242,30 +174,33 @@
         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
@@ -273,7 +208,7 @@
         assertExpectException(
                 IllegalArgumentException.class,
                 /* expectedExceptionMessageRegex */ "Unknown key: -1",
-                () -> new IntAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
+                () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
     }
 
     @Test
@@ -281,7 +216,123 @@
         assertExpectException(
                 IllegalArgumentException.class,
                 /* expectedExceptionMessageRegex */ "Unknown operator: -1",
-                () -> new IntAtomicFormula(AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
+                () ->
+                        new AtomicFormula.LongAtomicFormula(
+                                AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
+    }
+
+    @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..fa3d671 100644
--- a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
@@ -18,9 +18,9 @@
 
 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 android.os.Parcel;
 
@@ -38,7 +38,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() {
@@ -75,142 +75,6 @@
     }
 
     @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));
-    }
-
-    @Test
     public void testParcelUnparcel() {
         CompoundFormula formula =
                 new CompoundFormula(
@@ -234,6 +98,135 @@
                                 Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
     }
 
+    @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. */
     private AppInstallMetadata.Builder getAppInstallMetadataBuilder() {
         return new AppInstallMetadata.Builder()
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..639adf6
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.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() {
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class,
+                "must have even length",
+                () -> IntegrityUtils.getBytesFromHexDigest("ABC"));
+
+        TestUtils.assertExpectException(
+                IllegalArgumentException.class,
+                "Invalid hex char",
+                () -> IntegrityUtils.getBytesFromHexDigest("GH"));
+    }
+}
diff --git a/core/tests/coretests/src/android/content/integrity/RuleTest.java b/core/tests/coretests/src/android/content/integrity/RuleTest.java
index 19e74e6..8c4cfca 100644
--- a/core/tests/coretests/src/android/content/integrity/RuleTest.java
+++ b/core/tests/coretests/src/android/content/integrity/RuleTest.java
@@ -35,11 +35,15 @@
     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
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/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 f2852fa..bcf0b8c 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -41,6 +41,7 @@
 import android.util.SparseArray;
 import android.view.SurfaceControl.Transaction;
 import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.animation.LinearInterpolator;
 import android.view.test.InsetsModeSession;
 
 import androidx.test.runner.AndroidJUnit4;
@@ -121,7 +122,7 @@
         controls.put(ITYPE_NAVIGATION_BAR, navConsumer.getControl());
         mController = new InsetsAnimationControlImpl(controls,
                 new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
-                mMockController, 10 /* durationMs */,
+                mMockController, 10 /* durationMs */, new LinearInterpolator(),
                 false /* fade */, LAYOUT_INSETS_DURING_ANIMATION_SHOWN);
     }
 
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 8381903..f720c98 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -44,6 +44,7 @@
 import android.view.WindowInsets.Type;
 import android.view.WindowManager.BadTokenException;
 import android.view.WindowManager.LayoutParams;
+import android.view.animation.LinearInterpolator;
 import android.view.test.InsetsModeSession;
 import android.widget.TextView;
 
@@ -148,7 +149,7 @@
             WindowInsetsAnimationControlListener mockListener =
                     mock(WindowInsetsAnimationControlListener.class);
             mController.controlWindowInsetsAnimation(statusBars(), 10 /* durationMs */,
-                    mockListener);
+                    new LinearInterpolator(), mockListener);
 
             // Ready gets deferred until next predraw
             mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
@@ -164,7 +165,8 @@
         mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200));
         WindowInsetsAnimationControlListener controlListener =
                 mock(WindowInsetsAnimationControlListener.class);
-        mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, controlListener);
+        mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, new LinearInterpolator(),
+                controlListener);
         verify(controlListener).onCancelled();
         verify(controlListener, never()).onReady(any(), anyInt());
     }
@@ -375,7 +377,7 @@
             WindowInsetsAnimationControlListener mockListener =
                     mock(WindowInsetsAnimationControlListener.class);
             mController.controlWindowInsetsAnimation(statusBars(), 0 /* durationMs */,
-                    mockListener);
+                    new LinearInterpolator(), mockListener);
 
             ArgumentCaptor<WindowInsetsAnimationController> controllerCaptor =
                     ArgumentCaptor.forClass(WindowInsetsAnimationController.class);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 9e4b1c5..20be8c2 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -94,7 +94,7 @@
             WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
                     DisplayCutout.NO_CUTOUT, null, null, SOFT_INPUT_ADJUST_RESIZE, 0, null);
             assertEquals(100, insets.getStableInsetBottom());
-            assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.systemBars()));
+            assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars()));
             assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
             assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
             assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.navigationBars()));
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index cf5d079..df6ed8c 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -109,7 +109,7 @@
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.statusBars());
+        assertEquals(0, attrs.getFitInsetsTypes() & Type.statusBars());
     }
 
     @Test
@@ -120,7 +120,7 @@
         attrs.flags = FLAG_LAYOUT_IN_SCREEN;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.statusBars());
+        assertEquals(0, attrs.getFitInsetsTypes() & Type.statusBars());
     }
 
     @Test
@@ -131,7 +131,7 @@
         attrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(0, attrs.getFitWindowInsetsTypes() & Type.systemBars());
+        assertEquals(0, attrs.getFitInsetsTypes() & Type.systemBars());
     }
 
     @Test
@@ -141,8 +141,8 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_TOAST);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(Type.systemBars(), attrs.getFitWindowInsetsTypes() & Type.systemBars());
-        assertEquals(true, attrs.getFitIgnoreVisibility());
+        assertEquals(Type.systemBars(), attrs.getFitInsetsTypes() & Type.systemBars());
+        assertEquals(true, attrs.isFitInsetsIgnoringVisibility());
     }
 
     @Test
@@ -152,8 +152,8 @@
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_SYSTEM_ALERT);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(Type.systemBars(), attrs.getFitWindowInsetsTypes() & Type.systemBars());
-        assertEquals(true, attrs.getFitIgnoreVisibility());
+        assertEquals(Type.systemBars(), attrs.getFitInsetsTypes() & Type.systemBars());
+        assertEquals(true, attrs.isFitInsetsIgnoringVisibility());
     }
 
     @Test
@@ -165,14 +165,14 @@
         final int sides = Side.TOP | Side.LEFT;
         final boolean fitMaxInsets = true;
         attrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-        attrs.setFitWindowInsetsTypes(types);
-        attrs.setFitWindowInsetsSides(sides);
-        attrs.setFitIgnoreVisibility(fitMaxInsets);
+        attrs.setFitInsetsTypes(types);
+        attrs.setFitInsetsSides(sides);
+        attrs.setFitInsetsIgnoringVisibility(fitMaxInsets);
         ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
 
-        assertEquals(types, attrs.getFitWindowInsetsTypes());
-        assertEquals(sides, attrs.getFitWindowInsetsSides());
-        assertEquals(fitMaxInsets, attrs.getFitIgnoreVisibility());
+        assertEquals(types, attrs.getFitInsetsTypes());
+        assertEquals(sides, attrs.getFitInsetsSides());
+        assertEquals(fitMaxInsets, attrs.isFitInsetsIgnoringVisibility());
     }
 
     private static class ViewRootImplAccessor {
diff --git a/core/tests/coretests/src/android/view/inputmethod/EditorInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/EditorInfoTest.java
index 68099fe..12c057f 100644
--- a/core/tests/coretests/src/android/view/inputmethod/EditorInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/EditorInfoTest.java
@@ -18,9 +18,15 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.UserHandle;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -71,4 +77,227 @@
             }
         }
     }
+
+    @Test
+    public void testNullTextInputComposeInitialSurroundingText() {
+        final Spannable testText = null;
+        final EditorInfo editorInfo = new EditorInfo();
+
+        try {
+            editorInfo.setInitialSurroundingText(testText);
+            fail("Shall not take null input");
+        } catch (NullPointerException expected) {
+            // Expected behavior, nothing to do.
+        }
+    }
+
+    @Test
+    public void testNonNullTextInputComposeInitialSurroundingText() {
+        final Spannable testText = createTestText(/* prependLength= */ 0,
+                EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH);
+        final EditorInfo editorInfo = new EditorInfo();
+
+        // Cursor at position 0.
+        int selectionLength = 0;
+        editorInfo.initialSelStart = 0;
+        editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
+        int expectedTextBeforeCursorLength = 0;
+        int expectedTextAfterCursorLength = testText.length();
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Cursor at the end.
+        editorInfo.initialSelStart = testText.length() - selectionLength;
+        editorInfo.initialSelEnd = testText.length();
+        expectedTextBeforeCursorLength = testText.length();
+        expectedTextAfterCursorLength = 0;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Cursor at the middle.
+        selectionLength = 2;
+        editorInfo.initialSelStart = testText.length() / 2;
+        editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
+        expectedTextBeforeCursorLength = editorInfo.initialSelStart;
+        expectedTextAfterCursorLength = testText.length() - editorInfo.initialSelEnd;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Accidentally swap selection start and end.
+        editorInfo.initialSelEnd = testText.length() / 2;
+        editorInfo.initialSelStart = editorInfo.initialSelEnd + selectionLength;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Invalid cursor position.
+        editorInfo.initialSelStart = -1;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo,
+                /* expectBeforeCursorLength= */null,
+                /* expectSelectionLength= */null,
+                /* expectAfterCursorLength= */null);
+    }
+
+    @Test
+    public void testTooLongTextInputComposeInitialSurroundingText() {
+        final Spannable testText = createTestText(/* prependLength= */ 0,
+                EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH + 2);
+        final EditorInfo editorInfo = new EditorInfo();
+
+        // Cursor at position 0.
+        int selectionLength = 0;
+        editorInfo.initialSelStart = 0;
+        editorInfo.initialSelEnd = 0 + selectionLength;
+        int expectedTextBeforeCursorLength = 0;
+        int expectedTextAfterCursorLength = editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Cursor at the end.
+        editorInfo.initialSelStart = testText.length() - selectionLength;
+        editorInfo.initialSelEnd = testText.length();
+        expectedTextBeforeCursorLength = editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH;
+        expectedTextAfterCursorLength = 0;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Cursor at the middle.
+        selectionLength = 2;
+        editorInfo.initialSelStart = testText.length() / 2;
+        editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
+        expectedTextBeforeCursorLength = Math.min(editorInfo.initialSelStart,
+                (int) (0.8 * (EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH - selectionLength)));
+        expectedTextAfterCursorLength = EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH
+                - expectedTextBeforeCursorLength - selectionLength;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Accidentally swap selection start and end.
+        editorInfo.initialSelEnd = testText.length() / 2;
+        editorInfo.initialSelStart = editorInfo.initialSelEnd + selectionLength;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength, selectionLength,
+                expectedTextAfterCursorLength);
+
+        // Selection too long, selected text should be dropped.
+        selectionLength = EditorInfo.MAX_INITIAL_SELECTION_LENGTH + 1;
+        editorInfo.initialSelStart = testText.length() / 2;
+        editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
+        expectedTextBeforeCursorLength = Math.min(editorInfo.initialSelStart,
+                (int) (0.8 * EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH));
+        expectedTextAfterCursorLength = testText.length() - editorInfo.initialSelEnd;
+
+        editorInfo.setInitialSurroundingText(testText);
+
+        assertExpectedTextLength(editorInfo, expectedTextBeforeCursorLength,
+                /* expectSelectionLength= */null, expectedTextAfterCursorLength);
+    }
+
+    @Test
+    public void testTooLongSubTextInputComposeInitialSurroundingText() {
+        final int prependLength = 5;
+        final int subTextLength = EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH;
+        final Spannable fullText = createTestText(prependLength, subTextLength);
+        final EditorInfo editorInfo = new EditorInfo();
+        // Cursor at the middle.
+        final int selectionLength = 2;
+        editorInfo.initialSelStart = fullText.length() / 2;
+        editorInfo.initialSelEnd = editorInfo.initialSelStart + selectionLength;
+        // #prependLength characters will be trimmed out.
+        final Spannable expectedTextBeforeCursor = createExpectedText(/* startNumber= */0,
+                editorInfo.initialSelStart - prependLength);
+        final Spannable expectedSelectedText = createExpectedText(
+                editorInfo.initialSelStart - prependLength, selectionLength);
+        final Spannable expectedTextAfterCursor = createExpectedText(
+                editorInfo.initialSelEnd - prependLength,
+                fullText.length() - editorInfo.initialSelEnd);
+
+        editorInfo.setInitialSurroundingSubText(fullText.subSequence(prependLength,
+                fullText.length()), prependLength);
+
+        assertTrue(TextUtils.equals(expectedTextBeforeCursor,
+                editorInfo.getInitialTextBeforeCursor(editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH,
+                        InputConnection.GET_TEXT_WITH_STYLES)));
+        assertTrue(TextUtils.equals(expectedSelectedText,
+                editorInfo.getInitialSelectedText(InputConnection.GET_TEXT_WITH_STYLES)));
+        assertTrue(TextUtils.equals(expectedTextAfterCursor,
+                editorInfo.getInitialTextAfterCursor(editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH,
+                        InputConnection.GET_TEXT_WITH_STYLES)));
+    }
+
+    private static void assertExpectedTextLength(EditorInfo editorInfo,
+            @Nullable Integer expectBeforeCursorLength, @Nullable Integer expectSelectionLength,
+            @Nullable Integer expectAfterCursorLength) {
+        final CharSequence textBeforeCursor =
+                editorInfo.getInitialTextBeforeCursor(editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH,
+                        InputConnection.GET_TEXT_WITH_STYLES);
+        final CharSequence selectedText =
+                editorInfo.getInitialSelectedText(InputConnection.GET_TEXT_WITH_STYLES);
+        final CharSequence textAfterCursor =
+                editorInfo.getInitialTextAfterCursor(editorInfo.MEMORY_EFFICIENT_TEXT_LENGTH,
+                        InputConnection.GET_TEXT_WITH_STYLES);
+
+        if (expectBeforeCursorLength == null) {
+            assertNull(textBeforeCursor);
+        } else {
+            assertEquals(expectBeforeCursorLength.intValue(), textBeforeCursor.length());
+        }
+
+        if (expectSelectionLength == null) {
+            assertNull(selectedText);
+        } else {
+            assertEquals(expectSelectionLength.intValue(), selectedText.length());
+        }
+
+        if (expectAfterCursorLength == null) {
+            assertNull(textAfterCursor);
+        } else {
+            assertEquals(expectAfterCursorLength.intValue(), textAfterCursor.length());
+        }
+    }
+
+    private static Spannable createTestText(int prependLength, int surroundingLength) {
+        final SpannableStringBuilder builder = new SpannableStringBuilder();
+        for (int i = 0; i < prependLength; i++) {
+            builder.append("a");
+        }
+
+        for (int i = 0; i < surroundingLength; i++) {
+            builder.append(Integer.toString(i % 10));
+        }
+        return builder;
+    }
+
+    private static Spannable createExpectedText(int startNumber, int length) {
+        final SpannableStringBuilder builder = new SpannableStringBuilder();
+        for (int i = startNumber; i < startNumber + length; i++) {
+            builder.append(Integer.toString(i % 10));
+        }
+        return builder;
+    }
 }
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 c086421..d4c3621 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -31,6 +31,7 @@
 import static com.android.internal.app.ChooserListAdapter.CALLER_TARGET_SCORE_BOOST;
 import static com.android.internal.app.ChooserListAdapter.SHORTCUT_TARGET_SCORE_BOOST;
 import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
+import static com.android.internal.app.MatcherUtils.first;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
@@ -63,6 +64,8 @@
 import android.graphics.drawable.Icon;
 import android.metrics.LogMaker;
 import android.net.Uri;
+import android.os.Bundle;
+import android.os.UserHandle;
 import android.service.chooser.ChooserTarget;
 
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -74,7 +77,11 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -85,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;
 
 /**
@@ -302,6 +311,7 @@
         assertThat(activity.getIsSelected(), is(true));
     }
 
+    @Ignore // b/148158199
     @Test
     public void noResultsFromPackageManager() {
         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -346,6 +356,9 @@
 
     @Test
     public void hasOtherProfileOneOption() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -372,9 +385,7 @@
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
+        waitForIdle();
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         waitForIdle();
@@ -383,6 +394,9 @@
 
     @Test
     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(3);
@@ -411,9 +425,6 @@
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(3);
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         waitForIdle();
@@ -422,6 +433,9 @@
 
     @Test
     public void hasLastChosenActivityAndOtherProfile() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         Intent sendIntent = createSendTextIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(3);
@@ -448,9 +462,6 @@
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(3);
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         waitForIdle();
@@ -967,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,
@@ -976,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
@@ -1035,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,
@@ -1044,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
@@ -1119,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,
@@ -1128,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
@@ -1161,6 +1181,123 @@
                 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
     }
 
+    @Test
+    public void testWorkTab_displayedWhenWorkProfileUserAvailable() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+        markWorkProfileUserAvailable();
+
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+
+        onView(withId(R.id.tabs)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testWorkTab_hiddenWhenWorkProfileUserNotAvailable() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+
+        onView(withId(R.id.tabs)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testWorkTab_eachTabUsesExpectedAdapter() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        int personalProfileTargets = 3;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(personalProfileTargets);
+        int workProfileTargets = 4;
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
+                workProfileTargets);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+        markWorkProfileUserAvailable();
+
+        final ChooserWrapperActivity activity =
+                mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+
+        assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
+        // The work list adapter must only be filled when we open the work tab
+        assertThat(activity.getWorkListAdapter().getCount(), is(0));
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+        assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
+        assertThat(activity.getPersonalListAdapter().getCount(), is(personalProfileTargets));
+        assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
+    }
+
+    @Test
+    public void testWorkTab_workProfileHasExpectedNumberOfTargets() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        int workProfileTargets = 4;
+        List<ResolvedComponentInfo> workResolvedComponentInfos =
+                createResolvedComponentsForTest(workProfileTargets);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+
+        final ChooserWrapperActivity activity =
+                mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+        waitForIdle();
+
+        assertThat(activity.getWorkListAdapter().getCount(), is(workProfileTargets));
+    }
+
+    @Ignore // b/148156663
+    @Test
+    public void testWorkTab_selectingWorkTabAppOpensAppInWorkProfile() throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        int workProfileTargets = 4;
+        List<ResolvedComponentInfo> workResolvedComponentInfos =
+                createResolvedComponentsForTest(workProfileTargets);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendTextIntent();
+        sendIntent.setType("TestType");
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+        waitForIdle();
+        // wait for the share sheet to expand
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+
+        onView(first(withText(workResolvedComponentInfos.get(0)
+                .getResolveInfoAt(0).activityInfo.applicationInfo.name)))
+                .perform(click());
+        waitForIdle();
+        assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
+    }
+
     private Intent createSendTextIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
@@ -1224,6 +1361,15 @@
         return infoList;
     }
 
+    private List<ResolvedComponentInfo> createResolvedComponentsForTestWithUserId(
+            int numberOfResults, int userId) {
+        List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
+        for (int i = 0; i < numberOfResults; i++) {
+            infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
+        }
+        return infoList;
+    }
+
     private List<ChooserTarget> createDirectShareTargets(int numberOfResults, String packageName) {
         Icon icon = Icon.createWithBitmap(createBitmap());
         String testTitle = "testTitle";
@@ -1308,4 +1454,8 @@
             assertEquals(cn.flattenToString(), ct.getComponentName().flattenToString());
         }
     }
+
+    private void markWorkProfileUserAvailable() {
+        sOverrides.workProfileUserHandle = UserHandle.of(10);
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 2a10443..eee62bb 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -17,6 +17,7 @@
 package com.android.internal.app;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.annotation.Nullable;
 import android.app.usage.UsageStatsManager;
@@ -29,6 +30,7 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Size;
 
@@ -51,6 +53,19 @@
         return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
     }
 
+    ChooserListAdapter getPersonalListAdapter() {
+        return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0))
+                .getListAdapter();
+    }
+
+    ChooserListAdapter getWorkListAdapter() {
+        if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
+            return null;
+        }
+        return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1))
+                .getListAdapter();
+    }
+
     boolean getIsSelected() { return mIsSuccessfullySelected; }
 
     UsageStatsManager getUsageStatsManager() {
@@ -79,7 +94,12 @@
 
     @Override
     protected ResolverListController createListController(UserHandle userHandle) {
-        return sOverrides.resolverListController;
+        if (userHandle == UserHandle.SYSTEM) {
+            when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
+            return sOverrides.resolverListController;
+        }
+        when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
+        return sOverrides.workResolverListController;
     }
 
     @Override
@@ -144,6 +164,15 @@
                 resolveInfoPresentationGetter);
     }
 
+    @Override
+    protected UserHandle getWorkProfileUserHandle() {
+        return sOverrides.workProfileUserHandle;
+    }
+
+    protected UserHandle getCurrentUserHandle() {
+        return mMultiProfilePagerAdapter.getCurrentUserHandle();
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -154,6 +183,7 @@
         public Function<PackageManager, PackageManager> createPackageManager;
         public Function<TargetInfo, Boolean> onSafelyStartCallback;
         public ResolverListController resolverListController;
+        public ResolverListController workResolverListController;
         public Boolean isVoiceInteraction;
         public boolean isImageType;
         public Cursor resolverCursor;
@@ -162,6 +192,7 @@
         public MetricsLogger metricsLogger;
         public int alternateProfileSetting;
         public Resources resources;
+        public UserHandle workProfileUserHandle;
 
         public void reset() {
             onSafelyStartCallback = null;
@@ -172,9 +203,11 @@
             resolverCursor = null;
             resolverForceException = false;
             resolverListController = mock(ResolverListController.class);
+            workResolverListController = mock(ResolverListController.class);
             metricsLogger = mock(MetricsLogger.class);
             alternateProfileSetting = 0;
             resources = null;
+            workProfileUserHandle = null;
         }
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/app/MatcherUtils.java b/core/tests/coretests/src/com/android/internal/app/MatcherUtils.java
new file mode 100644
index 0000000..a476631
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/MatcherUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+/**
+ * Utils for helping with more customized matching options, for example matching the first
+ * occurrence of a set criteria.
+ */
+public class MatcherUtils {
+
+    /**
+     * Returns a {@link Matcher} which only matches the first occurrence of a set criteria.
+     */
+    static <T> Matcher<T> first(final Matcher<T> matcher) {
+        return new BaseMatcher<T>() {
+            boolean isFirstMatch = true;
+
+            @Override
+            public boolean matches(final Object item) {
+                if (isFirstMatch && matcher.matches(item)) {
+                    isFirstMatch = false;
+                    return true;
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(final Description description) {
+                description.appendText("Returns the first matching item");
+            }
+        };
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 923ce3e..42f7736 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -19,13 +19,17 @@
 import static androidx.test.espresso.Espresso.onView;
 import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
 import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
+import static com.android.internal.app.MatcherUtils.first;
 import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo;
 import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
 
+import static org.hamcrest.CoreMatchers.allOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -33,6 +37,7 @@
 
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.RelativeLayout;
@@ -49,6 +54,9 @@
 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
 import com.android.internal.widget.ResolverDrawerLayout;
 
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -212,6 +220,9 @@
 
     @Test
     public void hasOtherProfileOneOption() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         Intent sendIntent = createSendImageIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -237,9 +248,6 @@
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         onView(withId(R.id.button_once))
@@ -250,6 +258,9 @@
 
     @Test
     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         Intent sendIntent = createSendImageIntent();
         List<ResolvedComponentInfo> resolvedComponentInfos =
                 createResolvedComponentsForTestWithOtherProfile(3);
@@ -279,9 +290,6 @@
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
 
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         onView(withId(R.id.button_once)).perform(click());
@@ -292,6 +300,9 @@
 
     @Test
     public void hasLastChosenActivityAndOtherProfile() throws Exception {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+
         // In this case we prefer the other profile and don't display anything about the last
         // chosen activity.
         Intent sendIntent = createSendImageIntent();
@@ -325,9 +336,6 @@
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
 
-        // Check that the "Other Profile" activity is put in the right spot
-        onView(withId(R.id.profile_button)).check(matches(
-                withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
                 .perform(click());
         onView(withId(R.id.button_once)).perform(click());
@@ -379,6 +387,222 @@
                 TextUtils.isEmpty(pg.getSubLabel()));
     }
 
+    @Test
+    public void testWorkTab_displayedWhenWorkProfileUserAvailable() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        Intent sendIntent = createSendImageIntent();
+        markWorkProfileUserAvailable();
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+
+        onView(withId(R.id.tabs)).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testWorkTab_hiddenWhenWorkProfileUserNotAvailable() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        Intent sendIntent = createSendImageIntent();
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+
+        onView(withId(R.id.tabs)).check(matches(not(isDisplayed())));
+    }
+
+    @Test
+    public void testWorkTab_workTabListEmptyBeforeGoingToTab() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(3);
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+        markWorkProfileUserAvailable();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+
+        assertThat(activity.getCurrentUserHandle().getIdentifier(), is(0));
+        // The work list adapter must only be filled when we open the work tab
+        assertThat(activity.getWorkListAdapter().getCount(), is(0));
+    }
+
+    @Test
+    public void testWorkTab_workTabUsesExpectedAdapter() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(3);
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+        markWorkProfileUserAvailable();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+
+        assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
+        assertThat(activity.getWorkListAdapter().getCount(), is(4));
+    }
+
+    @Test
+    public void testWorkTab_personalTabUsesExpectedAdapter() {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(3);
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+        markWorkProfileUserAvailable();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab)).perform(click());
+
+        assertThat(activity.getCurrentUserHandle().getIdentifier(), is(10));
+        assertThat(activity.getPersonalListAdapter().getCount(), is(3));
+    }
+
+    @Test
+    public void testWorkTab_workProfileHasExpectedNumberOfTargets() throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(3);
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab))
+                .perform(click());
+
+        waitForIdle();
+        assertThat(activity.getWorkListAdapter().getCount(), is(4));
+    }
+
+    @Test
+    public void testWorkTab_selectingWorkTabAppOpensAppInWorkProfile() throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        List<ResolvedComponentInfo> personalResolvedComponentInfos =
+                createResolvedComponentsForTest(3);
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab))
+                .perform(click());
+        waitForIdle();
+        // wait for the share sheet to expand
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+        onView(first(allOf(withText(workResolvedComponentInfos.get(0)
+                .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
+                .perform(click());
+        onView(withId(R.id.button_once))
+                .perform(click());
+
+        waitForIdle();
+        assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
+    }
+
+    @Test
+    public void testWorkTab_noPersonalApps_workTabHasExpectedNumberOfTargets()
+            throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+
+        final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab))
+                .perform(click());
+
+        waitForIdle();
+        assertThat(activity.getWorkListAdapter().getCount(), is(4));
+    }
+
+    @Ignore // b/148156663
+    @Test
+    public void testWorkTab_noPersonalApps_canStartWorkApps()
+            throws InterruptedException {
+        // enable the work tab feature flag
+        ResolverActivity.ENABLE_TABBED_VIEW = true;
+        markWorkProfileUserAvailable();
+        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
+        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
+        Intent sendIntent = createSendImageIntent();
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        mActivityRule.launchActivity(sendIntent);
+        waitForIdle();
+        onView(withText(R.string.resolver_work_tab))
+                .perform(click());
+        waitForIdle();
+        // wait for the share sheet to expand
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+        onView(first(allOf(withText(workResolvedComponentInfos.get(0)
+                .getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
+                .perform(click());
+        onView(withId(R.id.button_once))
+                .perform(click());
+        waitForIdle();
+
+        assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
+    }
+
     private Intent createSendImageIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
@@ -411,4 +635,8 @@
     private void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
+
+    private void markWorkProfileUserAvailable() {
+        ResolverWrapperActivity.sOverrides.workProfileUserHandle = UserHandle.of(10);
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
index 59634f6..d7db5f8 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverDataProvider.java
@@ -46,6 +46,12 @@
                 createResolverIntent(i), createResolveInfo(i, USER_SOMEONE_ELSE));
     }
 
+    static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i,
+            int userId) {
+        return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
+                createResolverIntent(i), createResolveInfo(i, userId));
+    }
+
     static ComponentName createComponentName(int i) {
         final String name = "component" + i;
         return new ComponentName("foo.bar." + name, name);
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
index c5d2cfa..36c8724 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java
@@ -17,12 +17,14 @@
 package com.android.internal.app;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Bundle;
 import android.os.UserHandle;
 
 import com.android.internal.app.chooser.TargetInfo;
@@ -49,6 +51,17 @@
         return (ResolverWrapperAdapter) mMultiProfilePagerAdapter.getActiveListAdapter();
     }
 
+    ResolverListAdapter getPersonalListAdapter() {
+        return ((ResolverListAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0));
+    }
+
+    ResolverListAdapter getWorkListAdapter() {
+        if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
+            return null;
+        }
+        return ((ResolverListAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1));
+    }
+
     @Override
     public boolean isVoiceInteraction() {
         if (sOverrides.isVoiceInteraction != null) {
@@ -68,7 +81,12 @@
 
     @Override
     protected ResolverListController createListController(UserHandle userHandle) {
-        return sOverrides.resolverListController;
+        if (userHandle == UserHandle.SYSTEM) {
+            when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
+            return sOverrides.resolverListController;
+        }
+        when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
+        return sOverrides.workResolverListController;
     }
 
     @Override
@@ -79,6 +97,20 @@
         return super.getPackageManager();
     }
 
+    protected UserHandle getCurrentUserHandle() {
+        return mMultiProfilePagerAdapter.getCurrentUserHandle();
+    }
+
+    @Override
+    protected UserHandle getWorkProfileUserHandle() {
+        return sOverrides.workProfileUserHandle;
+    }
+
+    @Override
+    public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
+        super.startActivityAsUser(intent, options, user);
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -89,13 +121,17 @@
         public Function<PackageManager, PackageManager> createPackageManager;
         public Function<TargetInfo, Boolean> onSafelyStartCallback;
         public ResolverListController resolverListController;
+        public ResolverListController workResolverListController;
         public Boolean isVoiceInteraction;
+        public UserHandle workProfileUserHandle;
 
         public void reset() {
             onSafelyStartCallback = null;
             isVoiceInteraction = null;
             createPackageManager = null;
             resolverListController = mock(ResolverListController.class);
+            workResolverListController = mock(ResolverListController.class);
+            workProfileUserHandle = null;
         }
     }
 }
\ No newline at end of file
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/data/etc/com.android.documentsui.xml b/data/etc/com.android.documentsui.xml
index 36b282c..4d98603 100644
--- a/data/etc/com.android.documentsui.xml
+++ b/data/etc/com.android.documentsui.xml
@@ -17,5 +17,6 @@
 <permissions>
     <privapp-permissions package="com.android.documentsui">
         <permission name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
     </privapp-permissions>
 </permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 877ef26..0541db1 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -60,10 +60,6 @@
         <group gid="log" />
     </permission>
 
-    <permission name="android.permission.WRITE_MEDIA_STORAGE" >
-        <group gid="media_rw" />
-    </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/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/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index 4a252af..4981792 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -14,39 +14,41 @@
  * limitations under the License.
  */
 
-X(Flush) 
-X(Save) 
-X(Restore) 
+X(Flush)
+X(Save)
+X(Restore)
 X(SaveLayer)
 X(SaveBehind)
-X(Concat) 
-X(SetMatrix) 
+X(Concat44)
+X(Concat)
+X(SetMatrix)
+X(Scale)
 X(Translate)
-X(ClipPath) 
-X(ClipRect) 
-X(ClipRRect) 
+X(ClipPath)
+X(ClipRect)
+X(ClipRRect)
 X(ClipRegion)
 X(DrawPaint)
 X(DrawBehind)
-X(DrawPath) 
-X(DrawRect) 
-X(DrawRegion) 
-X(DrawOval) 
+X(DrawPath)
+X(DrawRect)
+X(DrawRegion)
+X(DrawOval)
 X(DrawArc)
-X(DrawRRect) 
-X(DrawDRRect) 
-X(DrawAnnotation) 
-X(DrawDrawable) 
+X(DrawRRect)
+X(DrawDRRect)
+X(DrawAnnotation)
+X(DrawDrawable)
 X(DrawPicture)
-X(DrawImage) 
-X(DrawImageNine) 
-X(DrawImageRect) 
+X(DrawImage)
+X(DrawImageNine)
+X(DrawImageRect)
 X(DrawImageLattice)
 X(DrawTextBlob)
-X(DrawPatch) 
-X(DrawPoints) 
-X(DrawVertices) 
-X(DrawAtlas) 
+X(DrawPatch)
+X(DrawPoints)
+X(DrawVertices)
+X(DrawAtlas)
 X(DrawShadowRec)
 X(DrawVectorDrawable)
 X(DrawWebView)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index c0df2fa..dc467c4 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -130,6 +130,12 @@
     }
 };
 
+struct Concat44 final : Op {
+    static const auto kType = Type::Concat44;
+    Concat44(const SkScalar m[16]) { memcpy(colMajor, m, sizeof(colMajor)); }
+    SkScalar colMajor[16];
+    void draw(SkCanvas* c, const SkMatrix&) const { c->experimental_concat44(colMajor); }
+};
 struct Concat final : Op {
     static const auto kType = Type::Concat;
     Concat(const SkMatrix& matrix) : matrix(matrix) {}
@@ -144,6 +150,12 @@
         c->setMatrix(SkMatrix::Concat(original, matrix));
     }
 };
+struct Scale final : Op {
+    static const auto kType = Type::Scale;
+    Scale(SkScalar sx, SkScalar sy) : sx(sx), sy(sy) {}
+    SkScalar sx, sy;
+    void draw(SkCanvas* c, const SkMatrix&) const { c->scale(sx, sy); }
+};
 struct Translate final : Op {
     static const auto kType = Type::Translate;
     Translate(SkScalar dx, SkScalar dy) : dx(dx), dy(dy) {}
@@ -562,12 +574,18 @@
     this->push<SaveBehind>(0, subset);
 }
 
+void DisplayListData::concat44(const SkScalar colMajor[16]) {
+    this->push<Concat44>(0, colMajor);
+}
 void DisplayListData::concat(const SkMatrix& matrix) {
     this->push<Concat>(0, matrix);
 }
 void DisplayListData::setMatrix(const SkMatrix& matrix) {
     this->push<SetMatrix>(0, matrix);
 }
+void DisplayListData::scale(SkScalar sx, SkScalar sy) {
+    this->push<Scale>(0, sx, sy);
+}
 void DisplayListData::translate(SkScalar dx, SkScalar dy) {
     this->push<Translate>(0, dx, dy);
 }
@@ -823,12 +841,18 @@
     return false;
 }
 
+void RecordingCanvas::didConcat44(const SkScalar colMajor[16]) {
+    fDL->concat44(colMajor);
+}
 void RecordingCanvas::didConcat(const SkMatrix& matrix) {
     fDL->concat(matrix);
 }
 void RecordingCanvas::didSetMatrix(const SkMatrix& matrix) {
     fDL->setMatrix(matrix);
 }
+void RecordingCanvas::didScale(SkScalar sx, SkScalar sy) {
+    fDL->scale(sx, sy);
+}
 void RecordingCanvas::didTranslate(SkScalar dx, SkScalar dy) {
     fDL->translate(dx, dy);
 }
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 322eff2..7eb1ce3 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -82,8 +82,10 @@
     void saveBehind(const SkRect*);
     void restore();
 
+    void concat44(const SkScalar colMajor[16]);
     void concat(const SkMatrix&);
     void setMatrix(const SkMatrix&);
+    void scale(SkScalar, SkScalar);
     void translate(SkScalar, SkScalar);
     void translateZ(SkScalar);
 
@@ -153,8 +155,10 @@
 
     void onFlush() override;
 
+    void didConcat44(const SkScalar[16]) override;
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
+    void didScale(SkScalar, SkScalar) override;
     void didTranslate(SkScalar, SkScalar) override;
 
     void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;
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/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index a1b2b18..aa8849b 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -26,6 +26,7 @@
 #include "SkAndroidFrameworkUtils.h"
 #include "SkClipStack.h"
 #include "SkRect.h"
+#include "include/private/SkM44.h"
 
 namespace android {
 namespace uirenderer {
@@ -92,7 +93,7 @@
 
     SkIRect surfaceBounds = canvas->internal_private_getTopLayerBounds();
     SkIRect clipBounds = canvas->getDeviceClipBounds();
-    SkMatrix44 mat4(canvas->getTotalMatrix());
+    SkM44 mat4(canvas->experimental_getLocalToDevice());
     SkRegion clipRegion;
     canvas->temporary_internal_getRgnClip(&clipRegion);
 
@@ -118,7 +119,7 @@
 
         // update the matrix and clip that we pass to the WebView to match the coordinates of
         // the offscreen layer
-        mat4.preTranslate(-clipBounds.fLeft, -clipBounds.fTop, 0);
+        mat4.preTranslate(-clipBounds.fLeft, -clipBounds.fTop);
         clipBounds.offsetTo(0, 0);
         clipRegion.translate(-surfaceBounds.fLeft, -surfaceBounds.fTop);
 
@@ -126,7 +127,7 @@
         // we are drawing into a (clipped) offscreen layer so we must update the clip and matrix
         // from device coordinates to the layer's coordinates
         clipBounds.offset(-surfaceBounds.fLeft, -surfaceBounds.fTop);
-        mat4.preTranslate(-surfaceBounds.fLeft, -surfaceBounds.fTop, 0);
+        mat4.preTranslate(-surfaceBounds.fLeft, -surfaceBounds.fTop);
     }
 
     DrawGlInfo info;
@@ -137,7 +138,7 @@
     info.isLayer = fboID != 0;
     info.width = fboSize.width();
     info.height = fboSize.height();
-    mat4.asColMajorf(&info.transform[0]);
+    mat4.getColMajor(&info.transform[0]);
     info.color_space_ptr = canvas->imageInfo().colorSpace();
 
     // ensure that the framebuffer that the webview will render into is bound before we clear
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 1127926..68f1117 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -20,6 +20,7 @@
 #include <GrBackendDrawableInfo.h>
 #include <SkAndroidFrameworkUtils.h>
 #include <SkImage.h>
+#include "include/private/SkM44.h"
 #include <utils/Color.h>
 #include <utils/Trace.h>
 #include <utils/TraceUtils.h>
@@ -62,7 +63,7 @@
             renderthread::RenderThread::getInstance().vulkanManager();
     mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams());
 
-    SkMatrix44 mat4(mMatrix);
+    SkM44 mat4(mMatrix);
     VkFunctorDrawParams params{
             .width = mImageInfo.width(),
             .height = mImageInfo.height(),
@@ -72,7 +73,7 @@
             .clip_right = mClip.fRight,
             .clip_bottom = mClip.fBottom,
     };
-    mat4.asColMajorf(&params.transform[0]);
+    mat4.getColMajor(&params.transform[0]);
     params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
     params.color_attachment_index = vulkan_info.fColorAttachmentIndex;
     params.compatible_render_pass = vulkan_info.fCompatibleRenderPass;
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index 706325f..241d370 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -121,7 +121,7 @@
         glBindTexture(GL_TEXTURE_2D, 0);
 
         DrawGlInfo info;
-        SkMatrix44 mat4(canvas->getTotalMatrix());
+        SkM44 mat4(canvas->experimental_getLocalToDevice());
         SkIRect clipBounds = canvas->getDeviceClipBounds();
 
         info.clipLeft = clipBounds.fLeft;
@@ -131,7 +131,7 @@
         info.isLayer = true;
         info.width = mFBInfo.width();
         info.height = mFBInfo.height();
-        mat4.asColMajorf(&info.transform[0]);
+        mat4.getColMajor(&info.transform[0]);
         info.color_space_ptr = canvas->imageInfo().colorSpace();
 
         glViewport(0, 0, info.width, info.height);
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/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java
index b2314c5..572fbc3 100644
--- a/location/java/com/android/internal/location/ProviderRequest.java
+++ b/location/java/com/android/internal/location/ProviderRequest.java
@@ -118,6 +118,7 @@
         for (LocationRequest request : locationRequests) {
             request.writeToParcel(parcel, flags);
         }
+        parcel.writeParcelable(workSource, flags);
     }
 
     @Override
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/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index cb132f5..6e63d17 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -422,6 +422,40 @@
         return AudioFormat.filterPublicFormats(mPort.formats());
     }
 
+    /**
+     * Returns an array of supported encapsulation modes for the device.
+     *
+     * The array can include any of
+     * {@link AudioTrack#ENCAPSULATION_MODE_ELEMENTARY_STREAM},
+     * {@link AudioTrack#ENCAPSULATION_MODE_HANDLE}.
+     *
+     * @return An array of supported encapsulation modes for the device.  This
+     *     may be an empty array if no encapsulation modes are supported.
+     */
+    public @NonNull int[] getEncapsulationModes() {
+        // Implement a getter in r-dev or r-tv-dev as needed.
+        return new int[0];  // be careful of returning a copy of any internal data.
+    }
+
+    /**
+     * Returns an array of supported encapsulation metadata types for the device.
+     *
+     * The metadata type returned should be allowed for all encapsulation modes supported
+     * by the device.  Some metadata types may apply only to certain
+     * compressed stream formats, the returned list is the union of subsets.
+     *
+     * The array can include any of
+     * {@link AudioTrack#ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER},
+     * {@link AudioTrack#ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR}.
+     *
+     * @return An array of supported encapsulation metadata types for the device.  This
+     *     may be an empty array if no metadata types are supported.
+     */
+    public @NonNull int[] getEncapsulationMetadataTypes() {
+        // Implement a getter in r-dev or r-tv-dev as needed.
+        return new int[0];  // be careful of returning a copy of any internal data.
+    }
+
    /**
      * @return The device type identifier of the audio device (i.e. TYPE_BUILTIN_SPEAKER).
      */
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 8ad5c04..861b76d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4567,6 +4567,70 @@
     }
 
     /**
+     * @hide
+     * Sets an additional audio output device delay in milliseconds.
+     *
+     * The additional output delay is a request to the output device to
+     * delay audio presentation (generally with respect to video presentation for better
+     * synchronization).
+     * It may not be supported by all output devices,
+     * and typically increases the audio latency by the amount of additional
+     * audio delay requested.
+     *
+     * If additional audio delay is supported by an audio output device,
+     * it is expected to be supported for all output streams (and configurations)
+     * opened on that device.
+     *
+     * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
+     * @param delayMs delay in milliseconds desired.  This should be in range of {@code 0}
+     *     to the value returned by {@link #getMaxAdditionalOutputDeviceDelay()}.
+     * @return true if successful, false if the device does not support output device delay
+     *     or the delay is not in range of {@link #getMaxAdditionalOutputDeviceDelay()}.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public boolean setAdditionalOutputDeviceDelay(
+            @NonNull AudioDeviceInfo device, @IntRange(from = 0) int delayMs) {
+        Objects.requireNonNull(device);
+        // Implement the setter in r-dev or r-tv-dev as needed.
+        return false;
+    }
+
+    /**
+     * @hide
+     * Returns the current additional audio output device delay in milliseconds.
+     *
+     * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
+     * @return the additional output device delay. This is a non-negative number.
+     *     {@code 0} is returned if unsupported.
+     */
+    @SystemApi
+    @IntRange(from = 0)
+    public int getAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+        Objects.requireNonNull(device);
+        // Implement the getter in r-dev or r-tv-dev as needed.
+        return 0;
+    }
+
+    /**
+     * @hide
+     * Returns the maximum additional audio output device delay in milliseconds.
+     *
+     * @param device an instance of {@link AudioDeviceInfo} returned from {@link getDevices()}.
+     * @return the maximum output device delay in milliseconds that can be set.
+     *     This is a non-negative number
+     *     representing the additional audio delay supported for the device.
+     *     {@code 0} is returned if unsupported.
+     */
+    @SystemApi
+    @IntRange(from = 0)
+    public int getMaxAdditionalOutputDeviceDelay(@NonNull AudioDeviceInfo device) {
+        Objects.requireNonNull(device);
+        // Implement the getter in r-dev or r-tv-dev as needed.
+        return 0;
+    }
+
+    /**
      * Returns the estimated latency for the given stream type in milliseconds.
      *
      * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index 453704e..65f2f17 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -102,6 +102,12 @@
                                 criterion -> criterion.getIntProp());
     }
 
+    /** @return the userId's passed to {@link Builder#addMatchingUserId(int)}. */
+    public @NonNull int[] getMatchingUserIds() {
+        return getIntPredicates(AudioMixingRule.RULE_MATCH_USERID,
+                criterion -> criterion.getIntProp());
+    }
+
     /** @return the usages passed to {@link Builder#excludeUsage(int)}. */
     @AttributeUsage
     public @NonNull int[] getExcludeUsages() {
@@ -115,6 +121,12 @@
                                 criterion -> criterion.getIntProp());
     }
 
+    /** @return the userId's passed to {@link Builder#excludeUserId(int)}.  */
+    public @NonNull int[] getExcludeUserIds() {
+        return getIntPredicates(AudioMixingRule.RULE_EXCLUDE_USERID,
+                criterion -> criterion.getIntProp());
+    }
+
     private int[] getIntPredicates(int rule,
                                    ToIntFunction<AudioMixMatchCriterion> getPredicate) {
         return mAudioMixingRule.getCriteria().stream()
@@ -153,6 +165,7 @@
         private final MediaProjection mProjection;
         private int mUsageMatchType = MATCH_TYPE_UNSPECIFIED;
         private int mUidMatchType = MATCH_TYPE_UNSPECIFIED;
+        private int mUserIdMatchType = MATCH_TYPE_UNSPECIFIED;
 
         /** @param projection A MediaProjection that supports audio projection. */
         public Builder(@NonNull MediaProjection projection) {
@@ -202,6 +215,23 @@
         }
 
         /**
+         * Only capture audio output by app with the matching {@code userId}.
+         *
+         * <p>If called multiple times, will capture audio output by apps whose userId is any of the
+         * given userId's.
+         *
+         * @throws IllegalStateException if called in conjunction with {@link #excludeUserId(int)}.
+         */
+        public @NonNull Builder addMatchingUserId(int userId) {
+            Preconditions.checkState(
+                    mUserIdMatchType != MATCH_TYPE_EXCLUSIVE,
+                    ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder.addMixRule(AudioMixingRule.RULE_MATCH_USERID, userId);
+            mUserIdMatchType = MATCH_TYPE_INCLUSIVE;
+            return this;
+        }
+
+        /**
          * Only capture audio output that does not match the given {@link AudioAttributes}.
          *
          * <p>If called multiple times, will capture audio output that does not match any of the
@@ -238,6 +268,24 @@
         }
 
         /**
+         * Only capture audio output by apps that do not have the matching {@code userId}.
+         *
+         * <p>If called multiple times, will capture audio output by apps whose userId is not any of
+         * the given userId's.
+         *
+         * @throws IllegalStateException if called in conjunction with
+         * {@link #addMatchingUserId(int)}.
+         */
+        public @NonNull Builder excludeUserId(int userId) {
+            Preconditions.checkState(
+                    mUserIdMatchType != MATCH_TYPE_INCLUSIVE,
+                    ERROR_MESSAGE_MISMATCHED_RULES);
+            mAudioMixingRuleBuilder.excludeMixRule(AudioMixingRule.RULE_MATCH_USERID, userId);
+            mUserIdMatchType = MATCH_TYPE_EXCLUSIVE;
+            return this;
+        }
+
+        /**
          * Builds the configuration instance.
          *
          * @throws UnsupportedOperationException if the parameters set are incompatible.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 48d27fa..02cb8aa 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1169,6 +1169,13 @@
     /** see AudioPolicy.removeUidDeviceAffinities() */
     public static native int removeUidDeviceAffinities(int uid);
 
+    /** see AudioPolicy.setUserIdDeviceAffinities() */
+    public static native int setUserIdDeviceAffinities(int userId, @NonNull int[] types,
+            @NonNull String[] addresses);
+
+    /** see AudioPolicy.removeUserIdDeviceAffinities() */
+    public static native int removeUserIdDeviceAffinities(int userId);
+
     public static native int systemReady();
 
     public static native float getStreamVolumeDB(int stream, int index, int device);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1f61591..81275f6 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -256,6 +256,38 @@
      */
     public static final int ENCAPSULATION_MODE_HANDLE = 2;
 
+    /* Enumeration of metadata types permitted for use by
+     * encapsulation mode audio streams.
+     */
+    /** @hide */
+    @IntDef(prefix = { "ENCAPSULATION_METADATA_TYPE_" }, value = {
+        ENCAPSULATION_METADATA_TYPE_NONE, /* reserved */
+        ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER,
+        ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EncapsulationMetadataType {}
+
+    /**
+     * Reserved do not use.
+     * @hide
+     */
+    public static final int ENCAPSULATION_METADATA_TYPE_NONE = 0; // reserved
+
+    /**
+     * Encapsulation metadata type for framework tuner information.
+     *
+     * TODO(b/147778408) Link: Fill in Tuner API info.
+     */
+    public static final int ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER = 1;
+
+    /**
+     * Encapsulation metadata type for DVB AD descriptor.
+     *
+     * This metadata is formatted per ETSI TS 101 154 Table E.1: AD_descriptor.
+     */
+    public static final int ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR = 2;
+
     /* Dual Mono handling is used when a stereo audio stream
      * contains separate audio content on the left and right channels.
      * Such information about the content of the stream may be found, for example, in
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 7f1c692..1f97be5 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -266,6 +266,10 @@
 
     int removeUidDeviceAffinity(in IAudioPolicyCallback pcb, in int uid);
 
+    int setUserIdDeviceAffinity(in IAudioPolicyCallback pcb, in int userId, in int[] deviceTypes,
+             in String[] deviceAddresses);
+    int removeUserIdDeviceAffinity(in IAudioPolicyCallback pcb, in int userId);
+
     boolean hasHapticChannels(in Uri uri);
 
     boolean isCallScreeningModeSupported();
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..f61d55e 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,6 +47,7 @@
  * <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>
@@ -217,6 +220,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/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/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 8c204d2..bca3fa7 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -73,6 +73,12 @@
      * parameter is an instance of {@link java.lang.Integer}.
      */
     public static final int RULE_MATCH_UID = 0x1 << 2;
+    /**
+     * A rule requiring the userId of the audio stream to match that specified.
+     * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where the Object
+     * parameter is an instance of {@link java.lang.Integer}.
+     */
+    public static final int RULE_MATCH_USERID = 0x1 << 3;
 
     private final static int RULE_EXCLUSION_MASK = 0x8000;
     /**
@@ -94,6 +100,13 @@
     public static final int RULE_EXCLUDE_UID =
             RULE_EXCLUSION_MASK | RULE_MATCH_UID;
 
+    /**
+     * @hide
+     * A rule requiring the userId information to differ.
+     */
+    public static final int RULE_EXCLUDE_USERID =
+            RULE_EXCLUSION_MASK | RULE_MATCH_USERID;
+
     /** @hide */
     public static final class AudioMixMatchCriterion {
         @UnsupportedAppUsage
@@ -125,19 +138,20 @@
             dest.writeInt(mRule);
             final int match_rule = mRule & ~RULE_EXCLUSION_MASK;
             switch (match_rule) {
-            case RULE_MATCH_ATTRIBUTE_USAGE:
-                dest.writeInt(mAttr.getUsage());
-                break;
-            case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
-                dest.writeInt(mAttr.getCapturePreset());
-                break;
-            case RULE_MATCH_UID:
-                dest.writeInt(mIntProp);
-                break;
-            default:
-                Log.e("AudioMixMatchCriterion", "Unknown match rule" + match_rule
-                        + " when writing to Parcel");
-                dest.writeInt(-1);
+                case RULE_MATCH_ATTRIBUTE_USAGE:
+                    dest.writeInt(mAttr.getUsage());
+                    break;
+                case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+                    dest.writeInt(mAttr.getCapturePreset());
+                    break;
+                case RULE_MATCH_UID:
+                case RULE_MATCH_USERID:
+                    dest.writeInt(mIntProp);
+                    break;
+                default:
+                    Log.e("AudioMixMatchCriterion", "Unknown match rule" + match_rule
+                            + " when writing to Parcel");
+                    dest.writeInt(-1);
             }
         }
 
@@ -203,6 +217,7 @@
             case RULE_MATCH_ATTRIBUTE_USAGE:
             case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
             case RULE_MATCH_UID:
+            case RULE_MATCH_USERID:
                 return true;
             default:
                 return false;
@@ -225,6 +240,7 @@
             case RULE_MATCH_ATTRIBUTE_USAGE:
             case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
             case RULE_MATCH_UID:
+            case RULE_MATCH_USERID:
                 return true;
             default:
                 return false;
@@ -234,11 +250,12 @@
     private static boolean isPlayerRule(int rule) {
         final int match_rule = rule & ~RULE_EXCLUSION_MASK;
         switch (match_rule) {
-        case RULE_MATCH_ATTRIBUTE_USAGE:
-        case RULE_MATCH_UID:
-            return true;
-        default:
-            return false;
+            case RULE_MATCH_ATTRIBUTE_USAGE:
+            case RULE_MATCH_UID:
+            case RULE_MATCH_USERID:
+                return true;
+            default:
+                return false;
         }
     }
 
@@ -319,7 +336,8 @@
          * property to match against.
          * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
-         *     {@link AudioMixingRule#RULE_MATCH_UID}.
+         *     {@link AudioMixingRule#RULE_MATCH_UID} or
+         *     {@link AudioMixingRule#RULE_MATCH_USERID}.
          * @param property see the definition of each rule for the type to use (either an
          *     {@link AudioAttributes} or an {@link java.lang.Integer}).
          * @return the same Builder instance.
@@ -349,7 +367,8 @@
          * coming from the specified UID.
          * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE},
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
-         *     {@link AudioMixingRule#RULE_MATCH_UID}.
+         *     {@link AudioMixingRule#RULE_MATCH_UID} or
+         *     {@link AudioMixingRule#RULE_MATCH_USERID}.
          * @param property see the definition of each rule for the type to use (either an
          *     {@link AudioAttributes} or an {@link java.lang.Integer}).
          * @return the same Builder instance.
@@ -425,6 +444,8 @@
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or
          *     {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET},
          *     {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}.
+         *     {@link AudioMixingRule#RULE_MATCH_USERID},
+         *     {@link AudioMixingRule#RULE_EXCLUDE_USERID}.
          * @return the same Builder instance.
          * @throws IllegalArgumentException
          */
@@ -495,6 +516,20 @@
                                 }
                             }
                             break;
+                        case RULE_MATCH_USERID:
+                            // "userid"-based rule
+                            if (criterion.mIntProp == intProp.intValue()) {
+                                if (criterion.mRule == rule) {
+                                    // rule already exists, we're done
+                                    return this;
+                                } else {
+                                    // criterion already exists with a another rule,
+                                    // it is incompatible
+                                    throw new IllegalArgumentException("Contradictory rule exists"
+                                            + " for userId " + intProp);
+                                }
+                            }
+                            break;
                     }
                 }
                 // rule didn't exist, add it
@@ -504,6 +539,7 @@
                         mCriteria.add(new AudioMixMatchCriterion(attrToMatch, rule));
                         break;
                     case RULE_MATCH_UID:
+                    case RULE_MATCH_USERID:
                         mCriteria.add(new AudioMixMatchCriterion(intProp, rule));
                         break;
                     default:
@@ -530,6 +566,7 @@
                             .setInternalCapturePreset(preset).build();
                     break;
                 case RULE_MATCH_UID:
+                case RULE_MATCH_USERID:
                     intProp = new Integer(in.readInt());
                     break;
                 default:
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 27f02fe..32a4a4f 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -51,6 +51,7 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * @hide
@@ -404,7 +405,7 @@
 
     /**
      * @hide
-     * Configures the audio framework so that all audio stream originating from the given UID
+     * Configures the audio framework so that all audio streams originating from the given UID
      * can only come from a set of audio devices.
      * For this routing to be operational, a number of {@link AudioMix} instances must have been
      * previously registered on this policy, and routed to a super-set of the given audio devices
@@ -476,6 +477,78 @@
         }
     }
 
+    /**
+     * @hide
+     * Removes audio device affinity previously set by
+     * {@link #setUserIdDeviceAffinity(int, java.util.List)}.
+     * @param userId userId of the application affected.
+     * @return true if the change was successful, false otherwise.
+     */
+    @TestApi
+    @SystemApi
+    public boolean removeUserIdDeviceAffinity(int userId) {
+        synchronized (mLock) {
+            if (mStatus != POLICY_STATUS_REGISTERED) {
+                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
+            }
+            final IAudioService service = getService();
+            try {
+                final int status = service.removeUserIdDeviceAffinity(this.cb(), userId);
+                return (status == AudioManager.SUCCESS);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Dead object in removeUserIdDeviceAffinity", e);
+                return false;
+            }
+        }
+    }
+
+    /**
+     * @hide
+     * Configures the audio framework so that all audio streams originating from the given user
+     * can only come from a set of audio devices.
+     * For this routing to be operational, a number of {@link AudioMix} instances must have been
+     * previously registered on this policy, and routed to a super-set of the given audio devices
+     * with {@link AudioMix.Builder#setDevice(android.media.AudioDeviceInfo)}. Note that having
+     * multiple devices in the list doesn't imply the signals will be duplicated on the different
+     * audio devices, final routing will depend on the {@link AudioAttributes} of the sounds being
+     * played.
+     * @param userId Android user id to affect.
+     * @param devices list of devices to which the audio stream of the application may be routed.
+     * @return true if the change was successful, false otherwise.
+     */
+    @TestApi
+    @SystemApi
+    public boolean setUserIdDeviceAffinity(int userId, @NonNull List<AudioDeviceInfo> devices) {
+        Objects.requireNonNull(devices, "Illegal null list of audio devices");
+        synchronized (mLock) {
+            if (mStatus != POLICY_STATUS_REGISTERED) {
+                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
+            }
+            final int[] deviceTypes = new int[devices.size()];
+            final String[] deviceAddresses = new String[devices.size()];
+            int i = 0;
+            for (AudioDeviceInfo device : devices) {
+                if (device == null) {
+                    throw new IllegalArgumentException(
+                            "Illegal null AudioDeviceInfo in setUserIdDeviceAffinity");
+                }
+                deviceTypes[i] =
+                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
+                deviceAddresses[i] = device.getAddress();
+                i++;
+            }
+            final IAudioService service = getService();
+            try {
+                final int status = service.setUserIdDeviceAffinity(this.cb(),
+                        userId, deviceTypes, deviceAddresses);
+                return (status == AudioManager.SUCCESS);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Dead object in setUserIdDeviceAffinity", e);
+                return false;
+            }
+        }
+    }
+
     public void setRegistration(String regId) {
         synchronized (mLock) {
             mRegistrationId = regId;
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index c4ba0c1..b048158 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -197,6 +197,14 @@
                         textDump += "  exclude UID ";
                         textDump += criterion.mIntProp;
                         break;
+                    case AudioMixingRule.RULE_MATCH_USERID:
+                        textDump += "  match userId ";
+                        textDump += criterion.mIntProp;
+                        break;
+                    case AudioMixingRule.RULE_EXCLUDE_USERID:
+                        textDump += "  exclude userId ";
+                        textDump += criterion.mIntProp;
+                        break;
                     default:
                         textDump += "invalid rule!";
                 }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 9953626..870c1b4 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -146,6 +146,8 @@
      * the system but will not be published until {@link #setActive(boolean)
      * setActive(true)} is called. You must call {@link #release()} when
      * finished with the session.
+     * <p>
+     * Note that {@link RuntimeException} will be thrown if an app creates too many sessions.
      *
      * @param context The context to use to create the session.
      * @param tag A short name for debugging purposes.
@@ -163,6 +165,8 @@
      * The {@code sessionInfo} can include additional unchanging information about this session.
      * For example, it can include the version of the application, or the list of the custom
      * commands that this session supports.
+     * <p>
+     * Note that {@link RuntimeException} will be thrown if an app creates too many sessions.
      *
      * @param context The context to use to create the session.
      * @param tag A short name for debugging purposes.
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/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..bb86763 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
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 97a2b22..b6bd86b 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -124,15 +124,16 @@
     }
 
     /**
-     * Reserves the ID which is used by HAL to provide additional information for AV data.
+     * Gets the audio handle.
      *
-     * <p>The corresponding data is used and released by {@link android.media.AudioTrack}.
-     * <p>The data is also released when the {@link Filter} instance is closed.
+     * <p>Client gets audio handle from {@link MediaEvent}, and queues it to
+     * {@link android.media.AudioTrack} in
+     * {@link android.media.AudioTrack#ENCAPSULATION_MODE_HANDLE} format.
      *
-     * @return the reserved AV data ID.
-     * @hide
+     * @return the audio handle.
+     * @see android.media.AudioTrack#ENCAPSULATION_MODE_HANDLE
      */
-    public long reserveAvDataId() {
+    public long getAudioHandle() {
         // TODO: implement
         return mDataId;
     }
diff --git a/media/java/android/media/voice/KeyphraseModelManager.java b/media/java/android/media/voice/KeyphraseModelManager.java
new file mode 100644
index 0000000..3fa38e0
--- /dev/null
+++ b/media/java/android/media/voice/KeyphraseModelManager.java
@@ -0,0 +1,144 @@
+/*
+ * 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.media.voice;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.util.Slog;
+
+import com.android.internal.app.IVoiceInteractionManagerService;
+
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * This class provides management of voice based sound recognition models. Usage of this class is
+ * restricted to system or signature applications only. This allows OEMs to write apps that can
+ * manage voice based sound trigger models.
+ * Callers of this class are expected to have whitelist manifest permission MANAGE_VOICE_KEYPHRASES.
+ * Callers of this class are expected to be the designated voice interaction service via
+ * {@link Settings.Secure.VOICE_INTERACTION_SERVICE}.
+ * @hide
+ */
+@SystemApi
+public final class KeyphraseModelManager {
+    private static final boolean DBG = false;
+    private static final String TAG = "KeyphraseModelManager";
+
+    private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
+
+    /**
+     * @hide
+     */
+    public KeyphraseModelManager(
+            IVoiceInteractionManagerService voiceInteractionManagerService) {
+        if (DBG) {
+            Slog.i(TAG, "KeyphraseModelManager created.");
+        }
+        mVoiceInteractionManagerService = voiceInteractionManagerService;
+    }
+
+
+    /**
+     * Gets the registered sound model for keyphrase detection for the current user.
+     * The keyphraseId and locale passed must match a supported model passed in via
+     * {@link #updateKeyphraseSoundModel}.
+     * If the active voice interaction service changes from the current user, all requests will be
+     * rejected, and any registered models will be unregistered.
+     *
+     * @param keyphraseId The unique identifier for the keyphrase.
+     * @param locale The locale language tag supported by the desired model.
+     * @return Registered keyphrase sound model matching the keyphrase ID and locale. May be null if
+     * no matching sound model exists.
+     * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission
+     *                           or if the caller is not the active voice interaction service.
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
+    @Nullable
+    public SoundTrigger.KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId,
+            @NonNull Locale locale) {
+        Objects.requireNonNull(locale);
+        try {
+            return mVoiceInteractionManagerService.getKeyphraseSoundModel(keyphraseId,
+                    locale.toLanguageTag());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Add or update the given keyphrase sound model to the registered models pool for the current
+     * user.
+     * If a model exists with the same Keyphrase ID, locale, and user list. The registered model
+     * will be overwritten with the new model.
+     * If the active voice interaction service changes from the current user, all requests will be
+     * rejected, and any registered models will be unregistered.
+     *
+     * @param model Keyphrase sound model to be updated.
+     * @throws ServiceSpecificException Thrown with error code if failed to update the keyphrase
+     *                           sound model.
+     * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission
+     *                           or if the caller is not the active voice interaction service.
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
+    public void updateKeyphraseSoundModel(@NonNull SoundTrigger.KeyphraseSoundModel model) {
+        Objects.requireNonNull(model);
+        try {
+            int status = mVoiceInteractionManagerService.updateKeyphraseSoundModel(model);
+            if (status != SoundTrigger.STATUS_OK) {
+                throw new ServiceSpecificException(status);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Delete keyphrase sound model from the registered models pool for the current user matching\
+     * the keyphrase ID and locale.
+     * The keyphraseId and locale passed must match a supported model passed in via
+     * {@link #updateKeyphraseSoundModel}.
+     * If the active voice interaction service changes from the current user, all requests will be
+     * rejected, and any registered models will be unregistered.
+     *
+     * @param keyphraseId The unique identifier for the keyphrase.
+     * @param locale The locale language tag supported by the desired model.
+     * @throws ServiceSpecificException Thrown with error code if failed to delete the keyphrase
+     *                           sound model.
+     * @throws SecurityException Thrown when caller does not have MANAGE_VOICE_KEYPHRASES permission
+     *                           or if the caller is not the active voice interaction service.
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_VOICE_KEYPHRASES)
+    public void deleteKeyphraseSoundModel(int keyphraseId, @NonNull Locale locale) {
+        Objects.requireNonNull(locale);
+        try {
+            int status = mVoiceInteractionManagerService.deleteKeyphraseSoundModel(keyphraseId,
+                    locale.toLanguageTag());
+            if (status != SoundTrigger.STATUS_OK) {
+                throw new ServiceSpecificException(status);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
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/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..79bcc15 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;
     }
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/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/src/com/android/systemui/car/SystemUIPrimaryWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
index c7e14d6..3f55ac8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
@@ -113,7 +113,7 @@
                 PixelFormat.TRANSLUCENT);
         mLp.token = new Binder();
         mLp.gravity = Gravity.TOP;
-        mLp.setFitWindowInsetsTypes(/* types= */ 0);
+        mLp.setFitInsetsTypes(/* types= */ 0);
         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         mLp.setTitle("SystemUIPrimaryWindow");
         mLp.packageName = mContext.getPackageName();
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 78764dd..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();
@@ -296,7 +296,7 @@
             leftlp.windowAnimations = 0;
             leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
             leftlp.gravity = Gravity.LEFT;
-            leftlp.setFitWindowInsetsTypes(0 /* types */);
+            leftlp.setFitInsetsTypes(0 /* types */);
             mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
         }
         if (mRightNavigationBarWindow != null) {
@@ -314,7 +314,7 @@
             rightlp.windowAnimations = 0;
             rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
             rightlp.gravity = Gravity.RIGHT;
-            rightlp.setFitWindowInsetsTypes(0 /* types */);
+            rightlp.setFitInsetsTypes(0 /* types */);
             mWindowManager.addView(mRightNavigationBarWindow, rightlp);
         }
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index b2f8aad..07dbd66 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -249,7 +249,7 @@
                         | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
                 PixelFormat.TRANSLUCENT
         );
-        attrs.setFitWindowInsetsTypes(0 /* types */);
+        attrs.setFitInsetsTypes(0 /* types */);
         return attrs;
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 8c756ec..7dd3be4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -20,6 +20,7 @@
 import static android.content.DialogInterface.BUTTON_POSITIVE;
 import static android.os.UserManager.DISALLOW_ADD_USER;
 import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
+import static android.view.WindowInsets.Type.statusBars;
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
@@ -367,8 +368,8 @@
             window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
             window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                     | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
-            window.setFitWindowInsetsTypes(
-                    window.getFitWindowInsetsTypes() & ~WindowInsets.Type.statusBars());
+            window.getAttributes().setFitInsetsTypes(
+                    window.getAttributes().getFitInsetsTypes() & ~statusBars());
         }
 
         private void notifyUserSelected(UserRecord userRecord) {
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/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/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index c913999..1072076 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -62,6 +62,7 @@
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SELinux;
 import android.os.ServiceManager;
@@ -275,6 +276,9 @@
     private final Object mLock = new Object();
 
     @GuardedBy("mLock")
+    private RemoteCallback mConfigMonitorCallback;
+
+    @GuardedBy("mLock")
     private SettingsRegistry mSettingsRegistry;
 
     @GuardedBy("mLock")
@@ -450,8 +454,17 @@
 
             case Settings.CALL_METHOD_LIST_CONFIG: {
                 String prefix = getSettingPrefix(args);
-                return packageValuesForCallResult(getAllConfigFlags(prefix),
+                Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix),
                         isTrackingGeneration(args));
+                reportDeviceConfigAccess(prefix);
+                return result;
+            }
+
+            case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG: {
+                RemoteCallback callback = args.getParcelable(
+                        Settings.CALL_METHOD_MONITOR_CALLBACK_KEY);
+                setMonitorCallback(callback);
+                break;
             }
 
             case Settings.CALL_METHOD_LIST_GLOBAL: {
@@ -1052,8 +1065,9 @@
         enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG);
 
         synchronized (mLock) {
-            return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM,
-                    prefix, keyValues, resolveCallingPackage());
+            final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
+            return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues,
+                    resolveCallingPackage());
         }
     }
 
@@ -2155,6 +2169,59 @@
         return result;
     }
 
+    private void setMonitorCallback(RemoteCallback callback) {
+        if (callback == null) {
+            return;
+        }
+        getContext().enforceCallingOrSelfPermission(
+                Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS,
+                "Permission denial: registering for config access requires: "
+                        + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS);
+        synchronized (mLock) {
+            mConfigMonitorCallback = callback;
+        }
+    }
+
+    private void reportDeviceConfigAccess(@Nullable String prefix) {
+        if (prefix == null) {
+            return;
+        }
+        String callingPackage = getCallingPackage();
+        String namespace = prefix.replace("/", "");
+        if (DeviceConfig.getPublicNamespaces().contains(namespace)) {
+            return;
+        }
+        synchronized (mLock) {
+            if (mConfigMonitorCallback != null) {
+                Bundle callbackResult = new Bundle();
+                callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE,
+                        Settings.EXTRA_ACCESS_CALLBACK);
+                callbackResult.putString(Settings.EXTRA_CALLING_PACKAGE, callingPackage);
+                callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace);
+                mConfigMonitorCallback.sendResult(callbackResult);
+            }
+        }
+    }
+
+    private void reportDeviceConfigUpdate(@Nullable String prefix) {
+        if (prefix == null) {
+            return;
+        }
+        String namespace = prefix.replace("/", "");
+        if (DeviceConfig.getPublicNamespaces().contains(namespace)) {
+            return;
+        }
+        synchronized (mLock) {
+            if (mConfigMonitorCallback != null) {
+                Bundle callbackResult = new Bundle();
+                callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE,
+                        Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK);
+                callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace);
+                mConfigMonitorCallback.sendResult(callbackResult);
+            }
+        }
+    }
+
     private static int getRequestingUserId(Bundle args) {
         final int callingUserId = UserHandle.getCallingUserId();
         return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId)
@@ -2715,22 +2782,20 @@
         }
 
         /**
-         * Set Settings using consumed keyValues, returns true if the keyValues can be set, false
-         * otherwise.
+         * Set Config Settings using consumed keyValues, returns true if the keyValues can be set,
+         * false otherwise.
          */
-        public boolean setSettingsLocked(int type, int userId, String prefix,
+        public boolean setConfigSettingsLocked(int key, String prefix,
                 Map<String, String> keyValues, String packageName) {
-            final int key = makeKey(type, userId);
-
             SettingsState settingsState = peekSettingsStateLocked(key);
             if (settingsState != null) {
-                if (SETTINGS_TYPE_CONFIG == type && settingsState.isNewConfigBannedLocked(prefix,
-                        keyValues)) {
+                if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) {
                     return false;
                 }
                 List<String> changedSettings =
                         settingsState.setSettingsLocked(prefix, keyValues, packageName);
                 if (!changedSettings.isEmpty()) {
+                    reportDeviceConfigUpdate(prefix);
                     notifyForConfigSettingsChangeLocked(key, prefix, changedSettings);
                 }
             }
@@ -4423,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..d40e7d4 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -239,6 +239,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/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/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/values/config.xml b/packages/SystemUI/res/values/config.xml
index e520106..edcd801 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -296,6 +296,7 @@
         <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>
     </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..b40c5c0 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>
 
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/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/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/UniversalSmartspaceUtils.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java
index 70a464d..871cae3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/UniversalSmartspaceUtils.java
@@ -37,7 +37,7 @@
         Intent intent = new Intent(ACTION_REQUEST_SMARTSPACE_VIEW);
 
         Bundle inputBundle = new Bundle();
-        inputBundle.putBinder(BUNDLE_KEY_INPUT_TOKEN, surfaceView.getInputToken());
+        inputBundle.putBinder(BUNDLE_KEY_INPUT_TOKEN, surfaceView.getHostToken());
         return intent
                 .putExtra(INTENT_KEY_SURFACE_CONTROL, surfaceView.getSurfaceControl())
                 .putExtra(INTENT_KEY_INPUT_BUNDLE, inputBundle)
diff --git a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
index 2f8ef2d..b2423b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java
@@ -172,7 +172,7 @@
 
     private void onSurfaceReady() {
         try {
-            mClient.onSurfaceReady(mView.getInputToken(), mCallback);
+            mClient.onSurfaceReady(mView.getHostToken(), mCallback);
         } catch (RemoteException e) {
             Log.e(TAG, "Error in onSurfaceReady", e);
             dismiss(KeyguardUpdateMonitor.getCurrentUser());
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 4e7956d..571c4ae 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -290,7 +290,7 @@
                     View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                             | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                             | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-            getWindow().setFitWindowInsetsTypes(0 /* types */);
+            getWindow().getAttributes().setFitInsetsTypes(0 /* types */);
             getWindow().setNavigationBarContrastEnforced(false);
             getWindow().setNavigationBarColor(Color.TRANSPARENT);
 
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/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/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index db8b583..e66b9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -503,7 +503,7 @@
             lp.gravity = Gravity.TOP | Gravity.LEFT;
         }
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        lp.setFitWindowInsetsTypes(0 /* types */);
+        lp.setFitInsetsTypes(0 /* types */);
         if (isLandscape(mRotation)) {
             lp.width = WRAP_CONTENT;
             lp.height = MATCH_PARENT;
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/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index 659629b..5532a04 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -70,7 +70,7 @@
                             | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
                     PixelFormat.TRANSLUCENT);
             lp.setTitle("AssistDisclosure");
-            lp.setFitWindowInsetsTypes(0 /* types */);
+            lp.setFitInsetsTypes(0 /* types */);
 
             mWm.addView(mView, lp);
             mViewAdded = true;
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
index eb615a0..f201a6f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -85,7 +85,7 @@
                 PixelFormat.TRANSLUCENT);
         mLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
         mLayoutParams.gravity = Gravity.BOTTOM;
-        mLayoutParams.setFitWindowInsetsTypes(0 /* types */);
+        mLayoutParams.setFitInsetsTypes(0 /* types */);
         mLayoutParams.setTitle("Assist");
 
         mInvocationLightsView = (InvocationLightsView)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 89446ad..b8d32ae 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -592,7 +592,7 @@
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("BiometricPrompt");
         lp.token = windowToken;
-        lp.setFitWindowInsetsTypes(lp.getFitWindowInsetsTypes() & ~Type.statusBars());
+        lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~Type.statusBars());
         return lp;
     }
 }
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..ccce85c 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;
@@ -93,6 +95,9 @@
     }
 
     private FlyoutMessage mFlyoutMessage;
+    private Bitmap mBadgedImage;
+    private int mDotColor;
+    private Path mDotPath;
 
     public static String groupId(NotificationEntry entry) {
         UserHandle user = entry.getSbn().getUser();
@@ -124,6 +129,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 +222,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);
     }
 
     /**
@@ -262,6 +283,13 @@
     }
 
     /**
+     * Should be invoked whenever a Bubble is promoted from overflow.
+     */
+    void markUpdatedAt(long lastAccessedMillis) {
+        mLastUpdated = lastAccessedMillis;
+    }
+
+    /**
      * Whether this notification should be shown in the shade when it is also displayed as a
      * bubble.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e642d4e..8c9946f 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;
@@ -301,6 +305,7 @@
 
         mBubbleData = data;
         mBubbleData.setListener(mBubbleDataListener);
+        mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
 
         mNotificationEntryManager = entryManager;
         mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
@@ -370,6 +375,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 +554,10 @@
         mBubbleData.setSelectedBubble(bubble);
     }
 
+    void promoteBubbleFromOverflow(Bubble bubble) {
+        mBubbleData.promoteBubbleFromOverflow(bubble);
+    }
+
     /**
      * Request the stack expand if needed, then select the specified Bubble as current.
      *
@@ -817,6 +838,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 +916,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 +940,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));
             }
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index cc0824e..8b687e7 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;
@@ -146,9 +151,11 @@
     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 boolean hasBubbles() {
@@ -184,6 +191,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)}
@@ -343,6 +363,7 @@
             mStateChange.orderChanged = true;
         }
         mStateChange.addedBubble = bubble;
+
         if (!isExpanded()) {
             mStateChange.orderChanged |= packGroup(findFirstIndexForGroup(bubble.getGroupId()));
             // Top bubble becomes selected.
@@ -407,6 +428,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 +486,7 @@
         if (mListener != null && mStateChange.anythingChanged()) {
             mListener.applyUpdate(mStateChange);
         }
-        mStateChange = new Update(mBubbles);
+        mStateChange = new Update(mBubbles, mOverflowBubbles);
     }
 
     /**
@@ -689,12 +721,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..fe4c915 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,
@@ -414,6 +418,10 @@
         setFocusable(true);
         mBubbleContainer.bringToFront();
 
+        if (BubbleExperimentConfig.allowBubbleOverflow(mContext)) {
+            setUpOverflow();
+        }
+
         setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
             if (!mIsExpanded || mIsExpansionAnimating) {
                 return view.onApplyWindowInsets(insets);
@@ -421,7 +429,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 +447,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 +517,51 @@
         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 -> {
+            showOverflow();
+        });
+
+        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 showOverflow() {
+        if (DEBUG_BUBBLE_STACK_VIEW) {
+            Log.d(TAG, "Show overflow.");
+        }
+        mExpandedViewContainer.setAlpha(0.0f);
+        mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
+            if (mExpandedBubble != null) {
+                mExpandedBubble.setContentVisibility(false);
+                mExpandedBubble = null;
+            }
+            mExpandedViewContainer.removeAllViews();
+            if (mIsExpanded) {
+                mExpandedViewContainer.addView(mOverflowExpandedView);
+                mOverflowExpandedView.populateExpandedView();
+                mExpandedViewContainer.setVisibility(VISIBLE);
+                mExpandedViewContainer.setAlpha(1.0f);
+                mOverflowExpandedView.setContentVisibility(true);
+            }
+            requestUpdate();
+        });
+    }
+
     private void setUpFlyout() {
         if (mFlyout != null) {
             removeView(mFlyout);
@@ -734,9 +797,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 +817,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
@@ -953,6 +1042,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 +1055,9 @@
                 () -> {
                     mBubbleContainer.setActiveController(mStackAnimationController);
                     afterExpandedViewAnimation();
-                    previouslySelected.setContentVisibility(false);
+                    if (previouslySelected != null) {
+                        previouslySelected.setContentVisibility(false);
+                    }
                 });
 
         mExpandedViewXAnim.animateToFinalPosition(getCollapsedX());
@@ -975,12 +1072,12 @@
         beforeExpandedViewAnimation();
 
         mBubbleContainer.setActiveController(mExpandedAnimationController);
+        updateOverflowBtnVisibility(/* apply */ false);
         mExpandedAnimationController.expandFromStack(() -> {
             updatePointerPosition();
             afterExpandedViewAnimation();
         } /* after */);
 
-
         mExpandedViewContainer.setTranslationX(getCollapsedX());
         mExpandedViewContainer.setTranslationY(getCollapsedY());
         mExpandedViewContainer.setAlpha(0f);
@@ -1063,9 +1160,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);
@@ -1545,7 +1644,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 +1674,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 +1788,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..6e23777 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;
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/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 99dd5e2..d4e47f6 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;
@@ -140,6 +141,12 @@
     @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
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 3735198..83f6d45 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1577,7 +1577,7 @@
                     | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
             window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-            window.setFitWindowInsetsTypes(0 /* types */);
+            window.getAttributes().setFitInsetsTypes(0 /* types */);
             setTitle(R.string.global_actions);
 
             mPanelController = plugin;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index c911bf2..dd1856a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -126,7 +126,7 @@
         window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
         window.getAttributes().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-        window.setFitWindowInsetsTypes(0 /* types */);
+        window.getAttributes().setFitInsetsTypes(0 /* types */);
         window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         window.addFlags(
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 750cc60..b725811 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -109,7 +109,7 @@
             lp.setTitle("pip-dismiss-overlay");
             lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
             lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
-            lp.setFitWindowInsetsTypes(0 /* types */);
+            lp.setFitInsetsTypes(0 /* types */);
             mWindowManager.addView(mDismissView, lp);
         }
         mDismissView.animate().cancel();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 569f660..79a33c9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -38,6 +38,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 +57,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;
@@ -115,6 +118,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 +369,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) {
@@ -518,6 +529,7 @@
 
         // Listen for status bar state changes
         statusBarWinController.registerCallback(mStatusBarWindowCallback);
+        mScreenshotHelper = new ScreenshotHelper(context);
     }
 
     public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 1d649ee..fe84d818 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -138,7 +138,7 @@
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("ScreenPinningConfirmation");
         lp.gravity = Gravity.FILL;
-        lp.setFitWindowInsetsTypes(0 /* types */);
+        lp.setFitInsetsTypes(0 /* types */);
         return lp;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 50e9a51..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;
@@ -240,7 +242,7 @@
                 PixelFormat.TRANSLUCENT);
         mWindowLayoutParams.setTitle("ScreenshotAnimation");
         mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        mWindowLayoutParams.setFitWindowInsetsTypes(0 /* types */);
+        mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
         mDisplayMetrics = new DisplayMetrics();
@@ -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 16447fb..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;
@@ -156,7 +157,7 @@
                 PixelFormat.TRANSLUCENT);
         mWindowLayoutParams.setTitle("ScreenshotAnimation");
         mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        mWindowLayoutParams.setFitWindowInsetsTypes(0 /* types */);
+        mWindowLayoutParams.setFitInsetsTypes(0 /* types */);
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
         mDisplayMetrics = new DisplayMetrics();
@@ -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/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/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/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index 315ea0a..4f27c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -35,6 +35,7 @@
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.view.Window
 import android.view.WindowInsets.Type
+import android.view.WindowInsets.Type.statusBars
 import android.view.WindowManager
 import android.widget.TextView
 import com.android.internal.annotations.VisibleForTesting
@@ -288,13 +289,13 @@
                 setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
                 addFlags(wmFlags)
                 setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL)
-                setFitWindowInsetsTypes(getFitWindowInsetsTypes() and Type.statusBars().inv())
                 setWindowAnimations(com.android.internal.R.style.Animation_InputMethod)
 
                 attributes = attributes.apply {
                     format = PixelFormat.TRANSLUCENT
                     title = ChannelEditorDialogController::class.java.simpleName
                     gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
+                    fitInsetsTypes = attributes.fitInsetsTypes and statusBars().inv()
                     width = MATCH_PARENT
                     height = WRAP_CONTENT
                 }
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 ef581db..6bd122d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -304,7 +304,7 @@
         layoutParams.setTitle(TAG + mContext.getDisplayId());
         layoutParams.accessibilityTitle = mContext.getString(R.string.nav_bar_edge_panel);
         layoutParams.windowAnimations = 0;
-        layoutParams.setFitWindowInsetsTypes(0 /* types */);
+        layoutParams.setFitInsetsTypes(0 /* types */);
         return layoutParams;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 783e7ad..16b5a23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -84,7 +84,7 @@
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("FloatingRotationButton");
-        lp.setFitWindowInsetsTypes(0 /*types */);
+        lp.setFitInsetsTypes(0 /*types */);
         switch (mWindowManager.getDefaultDisplay().getRotation()) {
             case Surface.ROTATION_0:
                 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
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/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index fe4879b..3af8038 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -175,7 +175,7 @@
                 PixelFormat.TRANSLUCENT);
         mLp.token = new Binder();
         mLp.gravity = Gravity.TOP;
-        mLp.setFitWindowInsetsTypes(0 /* types */);
+        mLp.setFitInsetsTypes(0 /* types */);
         mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         mLp.setTitle("NotificationShade");
         mLp.packageName = mContext.getPackageName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
index 6979554..7650a3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.WindowInsets.Type.systemBars;
+
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.LayoutRes;
@@ -81,7 +83,7 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
-        final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars());
+        final Insets insets = windowInsets.getInsetsIgnoringVisibility(systemBars());
         if (getFitsSystemWindows()) {
             boolean paddingChanged = insets.top != getPaddingTop()
                     || insets.bottom != getPaddingBottom();
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/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index fb30bde..e448d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -107,6 +107,7 @@
                 PixelFormat.TRANSLUCENT);
         mLp.token = new Binder();
         mLp.gravity = Gravity.TOP;
+        mLp.setFitInsetsTypes(0 /* types */);
         mLp.setTitle("StatusBar");
         mLp.packageName = mContext.getPackageName();
         mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
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/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 28b6c38..06105f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -106,8 +106,8 @@
         if (Dependency.get(KeyguardStateController.class).isShowing()) {
             final Window window = dialog.getWindow();
             window.setType(LayoutParams.TYPE_STATUS_BAR_PANEL);
-            window.setFitWindowInsetsTypes(
-                    window.getFitWindowInsetsTypes() & ~Type.statusBars());
+            window.getAttributes().setFitInsetsTypes(
+                    window.getAttributes().getFitInsetsTypes() & ~Type.statusBars());
         } else {
             dialog.getWindow().setType(LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
         }
@@ -118,8 +118,8 @@
         window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
         window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
-        window.setFitWindowInsetsTypes(
-                    window.getFitWindowInsetsTypes() & ~Type.statusBars());
+        window.getAttributes().setFitInsetsTypes(
+                window.getAttributes().getFitInsetsTypes() & ~Type.statusBars());
         return dialog;
     }
 
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/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index b09603d..1a2e237 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -257,7 +257,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 +269,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/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/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/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..79c6930 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,12 @@
      */
     public static final int TETHERING_WIFI_P2P = 3;
 
+    /**
+     * Ncm local tethering type.
+     * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
+     */
+    public static final int TETHERING_NCM = 4;
+
     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 +334,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 +538,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 +548,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 +660,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 +733,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 +841,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 +1009,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/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 0491ad7..57cc4dd 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -416,7 +416,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) {
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..02ba17e 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;
@@ -30,6 +31,7 @@
 import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
 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 +68,7 @@
 import android.content.res.Resources;
 import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
+import android.net.IIntResultListener;
 import android.net.INetd;
 import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
@@ -76,6 +79,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;
@@ -406,6 +410,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 +430,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 +445,36 @@
      * 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;
             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 +500,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,7 +534,7 @@
                 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);
@@ -799,6 +813,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 +841,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 +1144,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/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/system_messages.proto b/proto/src/system_messages.proto
index ad802ff..54b4201 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -312,5 +312,9 @@
     // Notify the user that data or apps are being moved to external storage.
     // Package: com.android.systemui
     NOTE_STORAGE_MOVE = 0x534d4f56;
+
+    // Notify the user that the admin suspended personal apps on the device.
+    // Package: android
+    NOTE_PERSONAL_APPS_SUSPENDED = 1003;
   }
 }
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/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/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/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/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 5e10916..0bcf45d 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -47,6 +47,7 @@
 import android.os.SELinux;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -399,6 +400,12 @@
      *                     the transport have no data.
      */
     private void informTransportOfUnchangedApps(Set<String> appsBackedUp) {
+        // If the feautre is not enabled then we just exit early.
+        if (!FeatureFlagUtils.isEnabled(mBackupManagerService.getContext(),
+                FeatureFlagUtils.BACKUP_NO_KV_DATA_CHANGE_CALLS)) {
+            return;
+        }
+
         String[] succeedingPackages = getSucceedingPackages();
         if (succeedingPackages == null) {
             // Nothing is succeeding, so end early.
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index e976811..434a97e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -361,13 +361,18 @@
         }
 
         @Override
-        public boolean isDeviceAssociated(String packageName, String macAddress, int userId) {
+        public boolean isDeviceAssociatedForWifiConnection(String packageName, String macAddress,
+                int userId) {
             getContext().enforceCallingOrSelfPermission(
                     android.Manifest.permission.MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
 
+            boolean bypassMacPermission = getContext().getPackageManager().checkPermission(
+                    android.Manifest.permission.COMPANION_APPROVE_WIFI_CONNECTIONS, packageName)
+                    == PackageManager.PERMISSION_GRANTED;
+
             return CollectionUtils.any(
                     readAllAssociations(userId, packageName),
-                    a -> Objects.equals(a.deviceAddress, macAddress));
+                    a -> bypassMacPermission || Objects.equals(a.deviceAddress, macAddress));
         }
 
         private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 8eca62a..9245a1d 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,16 @@
 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.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.
@@ -94,6 +112,9 @@
     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 +147,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();
 
@@ -618,6 +645,33 @@
         }
 
         @Override
+        public void shareData(@NonNull DataShareRequest request,
+                @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(mTag, "Failed to send error message to client");
+                    }
+                    return;
+                }
+
+                service.onDataSharedLocked(request,
+                        new DataShareCallbackDelegate(request, clientAdapter));
+            }
+        }
+
+        @Override
         public void isContentCaptureFeatureEnabled(@NonNull IResultReceiver result) {
             boolean enabled;
             synchronized (mLock) {
@@ -860,4 +914,179 @@
             }
         }
     }
+
+    // TODO(b/148265162): DataShareCallbackDelegate should be a static class keeping week references
+    //  to the needed info
+    private class DataShareCallbackDelegate extends IDataShareCallback.Stub {
+
+        @NonNull private final DataShareRequest mDataShareRequest;
+        @NonNull private final IDataShareWriteAdapter mClientAdapter;
+
+        DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest,
+                @NonNull IDataShareWriteAdapter clientAdapter) {
+            mDataShareRequest = dataShareRequest;
+            mClientAdapter = clientAdapter;
+        }
+
+        @Override
+        public void accept(IDataShareReadAdapter serviceAdapter)
+                            throws RemoteException {
+            Slog.i(mTag, "Data share request accepted by Content Capture service");
+
+            Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
+            if (clientPipe == null) {
+                mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                return;
+            }
+
+            ParcelFileDescriptor source_in = clientPipe.second;
+            ParcelFileDescriptor sink_in = clientPipe.first;
+
+            Pair<ParcelFileDescriptor, ParcelFileDescriptor> servicePipe = createPipe();
+            if (servicePipe == null) {
+                bestEffortCloseFileDescriptors(source_in, sink_in);
+
+                mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                return;
+            }
+
+            ParcelFileDescriptor source_out = servicePipe.second;
+            ParcelFileDescriptor sink_out = servicePipe.first;
+
+            ICancellationSignal cancellationSignalTransport =
+                    CancellationSignal.createTransport();
+            mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
+
+            mClientAdapter.write(source_in);
+            serviceAdapter.start(sink_out, cancellationSignalTransport);
+
+            // TODO(b/148264965): use cancellation signals for timeouts and cancelling
+            CancellationSignal cancellationSignal =
+                    CancellationSignal.fromTransport(cancellationSignalTransport);
+
+            cancellationSignal.setOnCancelListener(() -> {
+                try {
+                    // TODO(b/148264965): this should propagate with the cancellation signal to the
+                    // client
+                    mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                } catch (RemoteException e) {
+                    Slog.e(mTag, "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(source_in);
+
+            mDataShareExecutor.execute(() -> {
+                try (InputStream fis =
+                             new ParcelFileDescriptor.AutoCloseInputStream(sink_in);
+                     OutputStream fos =
+                             new ParcelFileDescriptor.AutoCloseOutputStream(source_out)) {
+
+                    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(mTag, "Failed to pipe client and service streams", e);
+                }
+            });
+
+            mHandler.postDelayed(() -> {
+                synchronized (mLock) {
+                    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 = !sink_in.getFileDescriptor().valid()
+                            && !source_out.getFileDescriptor().valid();
+
+                    if (finishedSuccessfully) {
+                        Slog.i(mTag, "Content capture data sharing session terminated "
+                                + "successfully for package '"
+                                + mDataShareRequest.getPackageName()
+                                + "'");
+                    } else {
+                        Slog.i(mTag, "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(source_in, sink_in, source_out, sink_out);
+
+                    if (!finishedSuccessfully) {
+                        try {
+                            mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                        } catch (RemoteException e) {
+                            Slog.e(mTag, "Failed to call error() to client", e);
+                        }
+                        try {
+                            serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                        } catch (RemoteException e) {
+                            Slog.e(mTag, "Failed to call error() to service", e);
+                        }
+                    }
+                }
+            }, MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
+        }
+
+        @Override
+        public void reject() throws RemoteException {
+            Slog.i(mTag, "Data share request rejected by Content Capture service");
+
+            mClientAdapter.rejected();
+        }
+
+        private Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
+            ParcelFileDescriptor[] fileDescriptors;
+            try {
+                fileDescriptors = ParcelFileDescriptor.createPipe();
+            } catch (IOException e) {
+                Slog.e(mTag, "Failed to create a content capture data-sharing pipe", e);
+                return null;
+            }
+
+            if (fileDescriptors.length != 2) {
+                Slog.e(mTag, "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(mTag, "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(mTag, "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/Android.bp b/services/core/Android.bp
index 1691a96..a603fa9 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -113,6 +113,7 @@
         "android.hardware.broadcastradio-V2.0-java",
         "android.hardware.health-V1.0-java",
         "android.hardware.health-V2.0-java",
+        "android.hardware.light-java",
         "android.hardware.weaver-V1.0-java",
         "android.hardware.biometrics.face-V1.0-java",
         "android.hardware.biometrics.fingerprint-V2.1-java",
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 368416b..27b6bfb 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -33,6 +33,7 @@
 import android.content.pm.parsing.ComponentParseUtils;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
@@ -169,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.
@@ -183,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);
@@ -251,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);
 
     /**
@@ -689,6 +702,27 @@
             int userId);
 
     /**
+     * Return the processes that have been declared for a uid.
+     *
+     * @param uid The uid to query.
+     *
+     * @return Returns null if there are no declared processes for the uid; otherwise,
+     * returns the set of processes it declared.
+     */
+    public abstract ArrayMap<String, ProcessInfo> getProcessesForUid(int uid);
+
+    /**
+     * Return the gids associated with a particular permission.
+     *
+     * @param permissionName The name of the permission to query.
+     * @param userId The user id the gids will be associated with.
+     *
+     * @return Returns null if there are no gids associated with the permission, otherwise an
+     * array if the gid ints.
+     */
+    public abstract int[] getPermissionGids(String permissionName, int userId);
+
+    /**
      * Return if device is currently in a "core" boot environment, typically
      * used to support full-disk encryption. Only apps marked with
      * {@code coreApp} attribute are available.
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index a33fcd5..8074900 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -66,8 +66,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.DumpUtils;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 
 import java.io.File;
 import java.io.FileDescriptor;
@@ -1065,7 +1065,7 @@
     }
 
     private final class Led {
-        private final Light mBatteryLight;
+        private final LogicalLight mBatteryLight;
 
         private final int mBatteryLowARGB;
         private final int mBatteryMediumARGB;
@@ -1100,7 +1100,7 @@
                     mBatteryLight.setColor(mBatteryLowARGB);
                 } else {
                     // Flash red when battery is low and not charging
-                    mBatteryLight.setFlashing(mBatteryLowARGB, Light.LIGHT_FLASH_TIMED,
+                    mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
                             mBatteryLedOn, mBatteryLedOff);
                 }
             } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1c9f5dc..dd33566 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) {
@@ -5798,7 +5820,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 +6019,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 +6067,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 +7331,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 e9db9c8..3b6ff26 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -18,6 +18,8 @@
 
 import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.location.LocationManager.FUSED_PROVIDER;
 import static android.location.LocationManager.GPS_PROVIDER;
@@ -35,14 +37,7 @@
 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.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.pm.Signature;
-import android.content.res.Resources;
-import android.hardware.location.ActivityRecognitionHardware;
 import android.location.Address;
 import android.location.Criteria;
 import android.location.GeocoderParams;
@@ -52,10 +47,12 @@
 import android.location.IGnssMeasurementsListener;
 import android.location.IGnssNavigationMessageListener;
 import android.location.IGnssStatusListener;
+import android.location.IGpsGeofenceHardware;
 import android.location.ILocationListener;
 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;
@@ -91,11 +88,11 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.location.AbstractLocationProvider;
 import com.android.server.location.AbstractLocationProvider.State;
-import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.CallerIdentity;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
 import com.android.server.location.GeofenceProxy;
+import com.android.server.location.HardwareActivityRecognitionProxy;
 import com.android.server.location.LocationFudger;
 import com.android.server.location.LocationProviderProxy;
 import com.android.server.location.LocationRequestStatistics;
@@ -114,7 +111,6 @@
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -123,6 +119,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;
 
@@ -137,11 +134,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
@@ -469,7 +467,7 @@
         mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
 
         for (LocationProviderManager manager : mProviderManagers) {
-            manager.onUseableChangedLocked(userId);
+            manager.onEnabledChangedLocked(userId);
         }
     }
 
@@ -543,77 +541,6 @@
     }
 
     @GuardedBy("mLock")
-    private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
-        PackageManager pm = mContext.getPackageManager();
-        String systemPackageName = mContext.getPackageName();
-        ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
-
-        List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
-                new Intent(FUSED_LOCATION_SERVICE_ACTION),
-                PackageManager.GET_META_DATA, mUserInfoStore.getCurrentUserId());
-        for (ResolveInfo rInfo : rInfos) {
-            String packageName = rInfo.serviceInfo.packageName;
-
-            // Check that the signature is in the list of supported sigs. If it's not in
-            // this list the standard provider binding logic won't bind to it.
-            try {
-                PackageInfo pInfo;
-                pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
-                if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
-                    Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
-                            ", but has wrong signature, ignoring");
-                    continue;
-                }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "missing package: " + packageName);
-                continue;
-            }
-
-            // Get the version info
-            if (rInfo.serviceInfo.metaData == null) {
-                Log.w(TAG, "Found fused provider without metadata: " + packageName);
-                continue;
-            }
-
-            int version = rInfo.serviceInfo.metaData.getInt(
-                    ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
-            if (version == 0) {
-                // This should be the fallback fused location provider.
-
-                // Make sure it's in the system partition.
-                if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
-                    continue;
-                }
-
-                // Check that the fallback is signed the same as the OS
-                // as a proxy for coreApp="true"
-                if (pm.checkSignatures(systemPackageName, packageName)
-                        != PackageManager.SIGNATURE_MATCH) {
-                    if (D) {
-                        Log.d(TAG, "Fallback candidate not signed the same as system: "
-                                + packageName);
-                    }
-                    continue;
-                }
-
-                // Found a valid fallback.
-                if (D) Log.d(TAG, "Found fallback provider: " + packageName);
-                return;
-            } else {
-                if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
-            }
-        }
-
-        throw new IllegalStateException("Unable to find a fused location provider that is in the "
-                + "system partition with version 0 and signed with the platform certificate. "
-                + "Such a package is needed to provide a default fused location provider in the "
-                + "event that no other fused location provider has been installed or is currently "
-                + "available. For example, coreOnly boot mode when decrypting the data "
-                + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
-    }
-
-    @GuardedBy("mLock")
     private void initializeProvidersLocked() {
         if (GnssManagerService.isGnssSupported()) {
             mGnssManagerService = new GnssManagerService(this, mContext, mLocationUsageLogger);
@@ -622,33 +549,11 @@
             gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
         }
 
-        /*
-        Load package name(s) containing location provider support.
-        These packages can contain services implementing location providers:
-        Geocoder Provider, Network Location Provider, and
-        Fused Location Provider. They will each be searched for
-        service components implementing these providers.
-        The location framework also has support for installation
-        of new location providers at run-time. The new package does not
-        have to be explicitly listed here, however it must have a signature
-        that matches the signature of at least one package on this list.
-        */
-        Resources resources = mContext.getResources();
-        String[] pkgs = resources.getStringArray(
-                com.android.internal.R.array.config_locationProviderPackageNames);
-        if (D) {
-            Log.d(TAG, "certificates for location providers pulled from: " +
-                    Arrays.toString(pkgs));
-        }
-
-        ensureFallbackFusedProviderPresentLocked(pkgs);
-
-        LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
+        LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister(
                 mContext,
                 NETWORK_LOCATION_SERVICE_ACTION,
                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
-                com.android.internal.R.string.config_networkLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
+                com.android.internal.R.string.config_networkLocationProviderPackageName);
         if (networkProvider != null) {
             LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
             mProviderManagers.add(networkManager);
@@ -657,13 +562,18 @@
             Slog.w(TAG, "no network location provider found");
         }
 
+        // ensure that a fused provider exists which will work in direct boot
+        Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
+                new Intent(FUSED_LOCATION_SERVICE_ACTION),
+                MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
+                "Unable to find a direct boot aware fused location provider");
+
         // bind to fused provider
-        LocationProviderProxy fusedProvider = LocationProviderProxy.createAndBind(
+        LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister(
                 mContext,
                 FUSED_LOCATION_SERVICE_ACTION,
                 com.android.internal.R.bool.config_enableFusedLocationOverlay,
-                com.android.internal.R.string.config_fusedLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
+                com.android.internal.R.string.config_fusedLocationProviderPackageName);
         if (fusedProvider != null) {
             LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
             mProviderManagers.add(fusedManager);
@@ -674,47 +584,30 @@
         }
 
         // bind to geocoder provider
-        mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
-                com.android.internal.R.bool.config_enableGeocoderOverlay,
-                com.android.internal.R.string.config_geocoderProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
+        mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
         if (mGeocodeProvider == null) {
             Slog.e(TAG, "no geocoder provider found");
         }
 
+        // bind to geofence proxy
         if (mGnssManagerService != null) {
-            // bind to geofence provider
-            GeofenceProxy provider = GeofenceProxy.createAndBind(
-                    mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
-                    com.android.internal.R.string.config_geofenceProviderPackageName,
-                    com.android.internal.R.array.config_locationProviderPackageNames,
-                    mGnssManagerService.getGpsGeofenceProxy(),
-                    null);
-            if (provider == null) {
-                Slog.d(TAG, "Unable to bind FLP Geofence proxy.");
+            IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
+            if (gpsGeofenceHardware != null) {
+                GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
+                if (provider == null) {
+                    Slog.d(TAG, "unable to bind to GeofenceProxy");
+                }
             }
         }
 
         // bind to hardware activity recognition
-        boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
-        ActivityRecognitionHardware activityRecognitionHardware = null;
-        if (activityRecognitionHardwareIsSupported) {
-            activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
-        } else {
-            Slog.d(TAG, "Hardware Activity-Recognition not supported.");
-        }
-        ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
-                mContext,
-                activityRecognitionHardwareIsSupported,
-                activityRecognitionHardware,
-                com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
-                com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
-        if (proxy == null) {
-            Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
+        HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
+                HardwareActivityRecognitionProxy.createAndRegister(mContext);
+        if (hardwareActivityRecognitionProxy == null) {
+            Log.e(TAG, "unable to bind ActivityRecognitionProxy");
         }
 
-        String[] testProviderStrings = resources.getStringArray(
+        String[] testProviderStrings = mContext.getResources().getStringArray(
                 com.android.internal.R.array.config_testLocationProviders);
         for (String testProviderString : testProviderStrings) {
             String[] fragments = testProviderString.split(",");
@@ -742,10 +635,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);
         }
     }
 
@@ -759,22 +652,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() {
@@ -802,13 +695,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);
             }
         }
 
@@ -869,7 +762,7 @@
                 return;
             }
 
-            if (!GPS_PROVIDER.equals(mName) || !isUseable()) {
+            if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
                 Slog.w(TAG, "reportLocationBatch() called without user permission");
                 return;
             }
@@ -880,30 +773,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;
@@ -913,36 +809,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.
@@ -950,7 +846,7 @@
                 mLastLocationCoarseInterval.clear();
             }
 
-            updateProviderUseableLocked(this);
+            updateProviderEnabledLocked(this);
         }
 
         public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
@@ -963,10 +859,10 @@
 
                 pw.increaseIndent();
 
-                boolean useable = isUseable();
-                pw.println("useable=" + useable);
-                if (!useable) {
-                    pw.println("enabled=" + mProvider.getState().enabled);
+                boolean enabled = isEnabled();
+                pw.println("enabled=" + enabled);
+                if (!enabled) {
+                    pw.println("allowed=" + mProvider.getState().allowed);
                 }
 
                 pw.println("properties=" + mProvider.getState().properties);
@@ -1118,7 +1014,7 @@
                     if (manager == null) {
                         continue;
                     }
-                    if (!manager.isUseable() && !isSettingsExemptLocked(updateRecord)) {
+                    if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) {
                         continue;
                     }
 
@@ -1534,7 +1430,7 @@
                 if (FUSED_PROVIDER.equals(name)) {
                     continue;
                 }
-                if (enabledOnly && !manager.isUseable()) {
+                if (enabledOnly && !manager.isEnabled()) {
                     continue;
                 }
                 if (criteria != null
@@ -1576,8 +1472,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;
 
@@ -1595,7 +1491,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<>();
                     }
@@ -1662,7 +1558,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);
@@ -2079,7 +1975,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);
@@ -2191,7 +2087,7 @@
                     return null;
                 }
 
-                if (!manager.isUseable()) {
+                if (!manager.isEnabled()) {
                     return null;
                 }
 
@@ -2313,7 +2209,7 @@
 
         synchronized (mLock) {
             LocationProviderManager manager = getLocationProviderManager(location.getProvider());
-            if (manager == null || !manager.isUseable()) {
+            if (manager == null || !manager.isEnabled()) {
                 return false;
             }
 
@@ -2600,7 +2496,7 @@
 
         synchronized (mLock) {
             LocationProviderManager manager = getLocationProviderManager(providerName);
-            return manager != null && manager.isUseable(userId);
+            return manager != null && manager.isEnabled(userId);
         }
     }
 
@@ -2658,8 +2554,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());
         }
 
@@ -2669,7 +2565,7 @@
         if (lastLocationCoarseInterval == null) {
             lastLocationCoarseInterval = new Location(location);
 
-            if (manager.isUseable()) {
+            if (manager.isEnabled()) {
                 mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
             }
         }
@@ -2702,7 +2598,7 @@
             Receiver receiver = r.mReceiver;
             boolean receiverDead = false;
 
-            if (!manager.isUseable() && !isSettingsExemptLocked(r)) {
+            if (!manager.isEnabled() && !isSettingsExemptLocked(r)) {
                 continue;
             }
 
@@ -2921,7 +2817,7 @@
             throw new IllegalArgumentException("provider doesn't exist: " + provider);
         }
 
-        manager.setMockProviderEnabled(enabled);
+        manager.setMockProviderAllowed(enabled);
     }
 
     @Override
@@ -2996,10 +2892,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();
 
@@ -3053,4 +2951,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/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index e8e3b39d..131a22b 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -18,6 +18,7 @@
 
 import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -25,14 +26,18 @@
 import android.content.pm.PackageManager;
 import android.content.pm.VersionedPackage;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Process;
 import android.os.RecoverySystem;
+import android.os.RemoteCallback;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
+import android.util.ArraySet;
 import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.MathUtils;
@@ -46,10 +51,16 @@
 import com.android.server.PackageWatchdog.PackageHealthObserver;
 import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
 import com.android.server.am.SettingsToPropertiesMapper;
-import com.android.server.utils.FlagNamespaceUtils;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Utilities to help rescue the system from crash loops. Callers are expected to
@@ -64,8 +75,6 @@
     @VisibleForTesting
     static final String PROP_ENABLE_RESCUE = "persist.sys.enable_rescue";
     @VisibleForTesting
-    static final int TRIGGER_COUNT = 5;
-    @VisibleForTesting
     static final String PROP_RESCUE_LEVEL = "sys.rescue_level";
     @VisibleForTesting
     static final int LEVEL_NONE = 0;
@@ -81,6 +90,8 @@
     static final String PROP_RESCUE_BOOT_COUNT = "sys.rescue_boot_count";
     @VisibleForTesting
     static final String TAG = "RescueParty";
+    @VisibleForTesting
+    static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2);
 
     private static final String NAME = "rescue-party-observer";
 
@@ -139,7 +150,11 @@
      */
     public static void onSettingsProviderPublished(Context context) {
         handleNativeRescuePartyResets();
-        executeRescueLevel(context);
+        executeRescueLevel(context, /*failedPackage=*/ null);
+        ContentResolver contentResolver = context.getContentResolver();
+        Settings.Config.registerMonitorCallback(contentResolver, new RemoteCallback(result -> {
+            handleMonitorCallback(context, result);
+        }));
     }
 
     @VisibleForTesting
@@ -147,10 +162,53 @@
         return SystemClock.elapsedRealtime();
     }
 
+    private static void handleMonitorCallback(Context context, Bundle result) {
+        String callbackType = result.getString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, "");
+        switch (callbackType) {
+            case Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK:
+                String updatedNamespace = result.getString(Settings.EXTRA_NAMESPACE);
+                if (updatedNamespace != null) {
+                    startObservingPackages(context, updatedNamespace);
+                }
+                break;
+            case Settings.EXTRA_ACCESS_CALLBACK:
+                String callingPackage = result.getString(Settings.EXTRA_CALLING_PACKAGE, null);
+                String namespace = result.getString(Settings.EXTRA_NAMESPACE, null);
+                if (namespace != null && callingPackage != null) {
+                    RescuePartyObserver.getInstance(context).recordDeviceConfigAccess(
+                            callingPackage,
+                            namespace);
+                }
+                break;
+            default:
+                Slog.w(TAG, "Unrecognized DeviceConfig callback");
+                break;
+        }
+    }
+
+    private static void startObservingPackages(Context context, @NonNull String updatedNamespace) {
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+        Set<String> callingPackages = rescuePartyObserver.getCallingPackagesSet(updatedNamespace);
+        if (callingPackages == null) {
+            return;
+        }
+        List<String> callingPackageList = new ArrayList<>();
+        callingPackageList.addAll(callingPackages);
+        Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
+                + updatedNamespace);
+        PackageWatchdog.getInstance(context).startObservingHealth(
+                rescuePartyObserver,
+                callingPackageList,
+                DEFAULT_OBSERVING_DURATION_MS);
+    }
+
     private static void handleNativeRescuePartyResets() {
         if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
-            FlagNamespaceUtils.resetDeviceConfig(Settings.RESET_MODE_TRUSTED_DEFAULTS,
-                    Arrays.asList(SettingsToPropertiesMapper.getResetNativeCategories()));
+            String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories();
+            for (int i = 0; i < resetNativeCategories.length; i++) {
+                DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
+                        resetNativeCategories[i]);
+            }
         }
     }
 
@@ -164,7 +222,7 @@
 
     /**
      * Escalate to the next rescue level. After incrementing the level you'll
-     * probably want to call {@link #executeRescueLevel(Context)}.
+     * probably want to call {@link #executeRescueLevel(Context, String)}.
      */
     private static void incrementRescueLevel(int triggerUid) {
         final int level = MathUtils.constrain(
@@ -177,13 +235,13 @@
                 + levelToString(level) + " triggered by UID " + triggerUid);
     }
 
-    private static void executeRescueLevel(Context context) {
+    private static void executeRescueLevel(Context context, @Nullable String failedPackage) {
         final int level = SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE);
         if (level == LEVEL_NONE) return;
 
         Slog.w(TAG, "Attempting rescue level " + levelToString(level));
         try {
-            executeRescueLevelInternal(context, level);
+            executeRescueLevelInternal(context, level, failedPackage);
             EventLogTags.writeRescueSuccess(level);
             logCriticalInfo(Log.DEBUG,
                     "Finished rescue level " + levelToString(level));
@@ -195,24 +253,23 @@
         }
     }
 
-    private static void executeRescueLevelInternal(Context context, int level) throws Exception {
+    private static void executeRescueLevelInternal(Context context, int level, @Nullable
+            String failedPackage) throws Exception {
         StatsLog.write(StatsLog.RESCUE_PARTY_RESET_REPORTED, level);
         switch (level) {
             case LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS:
-                resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+                resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_DEFAULTS, failedPackage);
                 break;
             case LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES:
-                resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES);
+                resetAllSettings(context, Settings.RESET_MODE_UNTRUSTED_CHANGES, failedPackage);
                 break;
             case LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS:
-                resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS);
+                resetAllSettings(context, Settings.RESET_MODE_TRUSTED_DEFAULTS, failedPackage);
                 break;
             case LEVEL_FACTORY_RESET:
                 RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
                 break;
         }
-        FlagNamespaceUtils.addToKnownResetNamespaces(
-                FlagNamespaceUtils.NAMESPACE_NO_PACKAGE);
     }
 
     private static int mapRescueLevelToUserImpact(int rescueLevel) {
@@ -237,13 +294,14 @@
         }
     }
 
-    private static void resetAllSettings(Context context, int mode) throws Exception {
+    private static void resetAllSettings(Context context, int mode, @Nullable String failedPackage)
+            throws Exception {
         // Try our best to reset all settings possible, and once finished
         // rethrow any exception that we encountered
         Exception res = null;
         final ContentResolver resolver = context.getContentResolver();
         try {
-            FlagNamespaceUtils.resetDeviceConfig(mode);
+            resetDeviceConfig(context, mode, failedPackage);
         } catch (Exception e) {
             res = new RuntimeException("Failed to reset config settings", e);
         }
@@ -264,6 +322,41 @@
         }
     }
 
+    private static void resetDeviceConfig(Context context, int resetMode,
+            @Nullable String failedPackage) {
+        if (!shouldPerformScopedResets() || failedPackage == null) {
+            DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null);
+        } else {
+            performScopedReset(context, resetMode, failedPackage);
+        }
+    }
+
+    private static boolean shouldPerformScopedResets() {
+        int rescueLevel = MathUtils.constrain(
+                SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE),
+                LEVEL_NONE, LEVEL_FACTORY_RESET);
+        return rescueLevel <= LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES;
+    }
+
+    private static void performScopedReset(Context context, int resetMode,
+            @NonNull String failedPackage) {
+        RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+        Set<String> affectedNamespaces = rescuePartyObserver.getAffectedNamespaceSet(
+                failedPackage);
+        if (affectedNamespaces == null) {
+            DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null);
+        } else {
+            Slog.w(TAG,
+                    "Performing scoped reset for package: " + failedPackage
+                            + ", affected namespaces: "
+                            + Arrays.toString(affectedNamespaces.toArray()));
+            Iterator<String> it = affectedNamespaces.iterator();
+            while (it.hasNext()) {
+                DeviceConfig.resetToDefaults(resetMode, it.next());
+            }
+        }
+    }
+
     /**
      * Handle mitigation action for package failures. This observer will be register to Package
      * Watchdog and will receive calls about package failures. This observer is persistent so it
@@ -271,7 +364,9 @@
      */
     public static class RescuePartyObserver implements PackageHealthObserver {
 
-        private Context mContext;
+        private final Context mContext;
+        private final Map<String, Set<String>> mCallingPackageNamespaceSetMap = new HashMap<>();
+        private final Map<String, Set<String>> mNamespaceCallingPackageSetMap = new HashMap<>();
 
         @GuardedBy("RescuePartyObserver.class")
         static RescuePartyObserver sRescuePartyObserver;
@@ -290,6 +385,13 @@
             }
         }
 
+        @VisibleForTesting
+        static void reset() {
+            synchronized (RescuePartyObserver.class) {
+                sRescuePartyObserver = null;
+            }
+        }
+
         @Override
         public int onHealthCheckFailed(@Nullable VersionedPackage failedPackage,
                 @FailureReasons int failureReason) {
@@ -314,7 +416,8 @@
                     || failureReason == PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING) {
                 int triggerUid = getPackageUid(mContext, failedPackage.getPackageName());
                 incrementRescueLevel(triggerUid);
-                executeRescueLevel(mContext);
+                executeRescueLevel(mContext,
+                        failedPackage == null ? null : failedPackage.getPackageName());
                 return true;
             } else {
                 return false;
@@ -355,7 +458,7 @@
                 return false;
             }
             incrementRescueLevel(Process.ROOT_UID);
-            executeRescueLevel(mContext);
+            executeRescueLevel(mContext, /*failedPackage=*/ null);
             return true;
         }
 
@@ -363,6 +466,32 @@
         public String getName() {
             return NAME;
         }
+
+        private synchronized void recordDeviceConfigAccess(@NonNull String callingPackage,
+                @NonNull String namespace) {
+            // Record it in calling packages to namespace map
+            Set<String> namespaceSet = mCallingPackageNamespaceSetMap.get(callingPackage);
+            if (namespaceSet == null) {
+                namespaceSet = new ArraySet<>();
+                mCallingPackageNamespaceSetMap.put(callingPackage, namespaceSet);
+            }
+            namespaceSet.add(namespace);
+            // Record it in namespace to calling packages map
+            Set<String> callingPackageSet = mNamespaceCallingPackageSetMap.get(namespace);
+            if (callingPackageSet == null) {
+                callingPackageSet = new ArraySet<>();
+            }
+            callingPackageSet.add(callingPackage);
+            mNamespaceCallingPackageSetMap.put(namespace, callingPackageSet);
+        }
+
+        private synchronized Set<String> getAffectedNamespaceSet(String failedPackage) {
+            return mCallingPackageNamespaceSetMap.get(failedPackage);
+        }
+
+        private synchronized Set<String> getCallingPackagesSet(String namespace) {
+            return mNamespaceCallingPackageSetMap.get(namespace);
+        }
     }
 
     private static int[] getAllUserIds() {
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index 7f51aa9..8564cb4 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -16,7 +16,19 @@
 
 package com.android.server;
 
+import static android.content.Context.BIND_AUTO_CREATE;
+import static android.content.Context.BIND_NOT_FOREGROUND;
+import static android.content.Context.BIND_NOT_VISIBLE;
+import static android.content.pm.PackageManager.GET_META_DATA;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
+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_SYSTEM_ONLY;
+
+import android.annotation.BoolRes;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -24,11 +36,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
-import android.content.pm.Signature;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Handler;
@@ -37,15 +45,10 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
-import android.util.Slog;
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.Preconditions;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Callable;
@@ -55,16 +58,16 @@
 import java.util.concurrent.TimeoutException;
 
 /**
- * Find the best Service, and bind to it.
- * Handles run-time package changes.
+ * Maintains a binding to the best service that matches the given intent information. Bind and
+ * unbind callbacks, as well as all binder operations, will all be run on the given handler.
  */
 public class ServiceWatcher implements ServiceConnection {
 
     private static final String TAG = "ServiceWatcher";
-    private static final boolean D = false;
+    private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
 
-    public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
-    public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
+    private static final String EXTRA_SERVICE_VERSION = "serviceVersion";
+    private static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
 
     private static final long BLOCKING_BINDER_TIMEOUT_MS = 30 * 1000;
 
@@ -83,280 +86,300 @@
         T run(IBinder binder) throws RemoteException;
     }
 
-    public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
-            String... packageNames) {
-        PackageManager pm = context.getPackageManager();
+    /**
+     * Information on the service ServiceWatcher has selected as the best option for binding.
+     */
+    public static final class ServiceInfo implements Comparable<ServiceInfo> {
 
-        ArrayList<HashSet<Signature>> signatureSets = new ArrayList<>(packageNames.length);
-        for (String packageName : packageNames) {
-            try {
-                Signature[] signatures = pm.getPackageInfo(packageName,
-                        PackageManager.MATCH_SYSTEM_ONLY
-                                | PackageManager.GET_SIGNATURES).signatures;
+        public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null,
+                UserHandle.USER_NULL);
 
-                HashSet<Signature> set = new HashSet<>();
-                Collections.addAll(set, signatures);
-                signatureSets.add(set);
-            } catch (NameNotFoundException e) {
-                Log.w(TAG, packageName + " not found");
+        public final int version;
+        @Nullable public final ComponentName component;
+        @UserIdInt public final int userId;
+
+        private ServiceInfo(ResolveInfo resolveInfo, int currentUserId) {
+            Preconditions.checkArgument(resolveInfo.serviceInfo.getComponentName() != null);
+
+            Bundle metadata = resolveInfo.serviceInfo.metaData;
+            boolean isMultiuser;
+            if (metadata != null) {
+                version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
+                isMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
+            } else {
+                version = Integer.MIN_VALUE;
+                isMultiuser = false;
             }
+
+            component = resolveInfo.serviceInfo.getComponentName();
+            userId = isMultiuser ? UserHandle.USER_SYSTEM : currentUserId;
         }
-        return signatureSets;
-    }
 
-    /** Checks if signatures match. */
-    public static boolean isSignatureMatch(Signature[] signatures,
-            List<HashSet<Signature>> sigSets) {
-        if (signatures == null) return false;
+        private ServiceInfo(int version, @Nullable ComponentName component, int userId) {
+            Preconditions.checkArgument(component != null || version == Integer.MIN_VALUE);
+            this.version = version;
+            this.component = component;
+            this.userId = userId;
+        }
 
-        // build hashset of input to test against
-        HashSet<Signature> inputSet = new HashSet<>();
-        Collections.addAll(inputSet, signatures);
-
-        // test input against each of the signature sets
-        for (HashSet<Signature> referenceSet : sigSets) {
-            if (referenceSet.equals(inputSet)) {
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
                 return true;
             }
+            if (!(o instanceof ServiceInfo)) {
+                return false;
+            }
+            ServiceInfo that = (ServiceInfo) o;
+            return version == that.version && userId == that.userId
+                    && Objects.equals(component, that.component);
         }
-        return false;
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(version, component, userId);
+        }
+
+        @Override
+        public int compareTo(ServiceInfo that) {
+            // ServiceInfos with higher version numbers always win (having a version number >
+            // MIN_VALUE implies having a non-null component). if version numbers are equal, a
+            // non-null component wins over a null component. if the version numbers are equal and
+            // both components exist then we prefer components that work for all users vs components
+            // that only work for a single user at a time. otherwise everything's equal.
+            int ret = Integer.compare(version, that.version);
+            if (ret == 0) {
+                if (component == null && that.component != null) {
+                    ret = -1;
+                } else if (component != null && that.component == null) {
+                    ret = 1;
+                } else {
+                    if (userId != UserHandle.USER_SYSTEM && that.userId == UserHandle.USER_SYSTEM) {
+                        ret = -1;
+                    } else if (userId == UserHandle.USER_SYSTEM
+                            && that.userId != UserHandle.USER_SYSTEM) {
+                        ret = 1;
+                    }
+                }
+            }
+            return ret;
+        }
+
+        @Override
+        public String toString() {
+            return component + "@" + version + "[u" + userId + "]";
+        }
     }
 
     private final Context mContext;
-    private final String mTag;
-    private final String mAction;
-    private final String mServicePackageName;
-    private final List<HashSet<Signature>> mSignatureSets;
-
     private final Handler mHandler;
+    private final Intent mIntent;
 
-    // read/write from handler thread
-    private IBinder mBestService;
+    @Nullable private final BinderRunner mOnBind;
+    @Nullable private final Runnable mOnUnbind;
+
+    // read/write from handler thread only
     private int mCurrentUserId;
 
-    // read from any thread, write from handler thread
-    private volatile ComponentName mBestComponent;
-    private volatile int mBestVersion;
-    private volatile int mBestUserId;
+    // write from handler thread only, read anywhere
+    private volatile ServiceInfo mServiceInfo;
 
-    public ServiceWatcher(Context context, String logTag, String action,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler) {
-        Resources resources = context.getResources();
+    // read/write from handler thread only
+    private IBinder mBinder;
 
+    public ServiceWatcher(Context context, Handler handler, String action,
+            @Nullable BinderRunner onBind, @Nullable Runnable onUnbind,
+            @BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) {
         mContext = context;
-        mTag = logTag;
-        mAction = action;
+        mHandler = FgThread.getHandler();
+        mIntent = new Intent(Objects.requireNonNull(action));
 
-        boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
-        if (enableOverlay) {
-            String[] pkgs = resources.getStringArray(initialPackageNamesResId);
-            mServicePackageName = null;
-            mSignatureSets = getSignatureSets(context, pkgs);
-            if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
-        } else {
-            mServicePackageName = resources.getString(defaultServicePackageNameResId);
-            mSignatureSets = getSignatureSets(context, mServicePackageName);
-            if (D) Log.d(mTag, "Overlay disabled, default package=" + mServicePackageName);
+        Resources resources = context.getResources();
+        boolean enableOverlay = resources.getBoolean(enableOverlayResId);
+        if (!enableOverlay) {
+            mIntent.setPackage(resources.getString(nonOverlayPackageResId));
         }
 
-        mHandler = handler;
+        mOnBind = onBind;
+        mOnUnbind = onUnbind;
 
-        mBestComponent = null;
-        mBestVersion = Integer.MIN_VALUE;
-        mBestUserId = UserHandle.USER_NULL;
+        mCurrentUserId = UserHandle.USER_NULL;
 
-        mBestService = null;
+        mServiceInfo = ServiceInfo.NONE;
+        mBinder = null;
     }
 
-    protected void onBind() {}
-
-    protected void onUnbind() {}
-
     /**
-     * Start this watcher, including binding to the current best match and
-     * re-binding to any better matches down the road.
-     * <p>
-     * Note that if there are no matching encryption-aware services, we may not
-     * bind to a real service until after the current user is unlocked.
-     *
-     * @return {@code true} if a potential service implementation was found.
+     * Register this class, which will start the process of determining the best matching service
+     * and maintaining a binding to it. Will return false and fail if there are no possible matching
+     * services at the time this functions is called.
      */
-    public final boolean start() {
-        // if we have to return false, do it before registering anything
-        if (isServiceMissing()) return false;
-
-        // listen for relevant package changes if service overlay is enabled on handler
-        if (mServicePackageName == null) {
-            new PackageMonitor() {
-                @Override
-                public void onPackageUpdateFinished(String packageName, int uid) {
-                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
-                }
-
-                @Override
-                public void onPackageAdded(String packageName, int uid) {
-                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
-                }
-
-                @Override
-                public void onPackageRemoved(String packageName, int uid) {
-                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
-                }
-
-                @Override
-                public boolean onPackageChanged(String packageName, int uid, String[] components) {
-                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
-                    return super.onPackageChanged(packageName, uid, components);
-                }
-            }.register(mContext, UserHandle.ALL, true, mHandler);
+    public boolean register() {
+        if (mContext.getPackageManager().queryIntentServicesAsUser(mIntent,
+                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE | MATCH_SYSTEM_ONLY,
+                UserHandle.USER_SYSTEM).isEmpty()) {
+            return false;
         }
 
-        // listen for user change on handler
+        new PackageMonitor() {
+            @Override
+            public void onPackageUpdateFinished(String packageName, int uid) {
+                ServiceWatcher.this.onPackageChanged(packageName);
+            }
+
+            @Override
+            public void onPackageAdded(String packageName, int uid) {
+                ServiceWatcher.this.onPackageChanged(packageName);
+            }
+
+            @Override
+            public void onPackageRemoved(String packageName, int uid) {
+                ServiceWatcher.this.onPackageChanged(packageName);
+            }
+
+            @Override
+            public boolean onPackageChanged(String packageName, int uid, String[] components) {
+                ServiceWatcher.this.onPackageChanged(packageName);
+                return super.onPackageChanged(packageName, uid, components);
+            }
+        }.register(mContext, UserHandle.ALL, true, mHandler);
+
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
         mContext.registerReceiverAsUser(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL);
-                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    mCurrentUserId = userId;
-                    bindBestPackage(false);
-                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
-                    if (userId == mCurrentUserId) {
-                        bindBestPackage(false);
-                    }
+                String action = intent.getAction();
+                if (action == null) {
+                    return;
                 }
+                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                if (userId == UserHandle.USER_NULL) {
+                    return;
+                }
+
+                switch (action) {
+                    case Intent.ACTION_USER_SWITCHED:
+                        onUserSwitched(userId);
+                        break;
+                    case Intent.ACTION_USER_UNLOCKED:
+                        onUserUnlocked(userId);
+                        break;
+                    default:
+                        break;
+                }
+
             }
         }, UserHandle.ALL, intentFilter, null, mHandler);
 
         mCurrentUserId = ActivityManager.getCurrentUser();
 
-        mHandler.post(() -> bindBestPackage(false));
+        mHandler.post(() -> onBestServiceChanged(false));
         return true;
     }
 
-    /** Returns the name of the currently connected package or null. */
-    @Nullable
-    public String getCurrentPackageName() {
-        ComponentName bestComponent = mBestComponent;
-        return bestComponent == null ? null : bestComponent.getPackageName();
+    /**
+     * Returns information on the currently selected service.
+     */
+    public ServiceInfo getBoundService() {
+        return mServiceInfo;
     }
 
-    private boolean isServiceMissing() {
-        return mContext.getPackageManager().queryIntentServicesAsUser(new Intent(mAction),
-                PackageManager.MATCH_DIRECT_BOOT_AWARE
-                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                UserHandle.USER_SYSTEM).isEmpty();
-    }
-
-    private void bindBestPackage(boolean forceRebind) {
+    private void onBestServiceChanged(boolean forceRebind) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
-        Intent intent = new Intent(mAction);
-        if (mServicePackageName != null) {
-            intent.setPackage(mServicePackageName);
-        }
-
-        List<ResolveInfo> rInfos = mContext.getPackageManager().queryIntentServicesAsUser(intent,
-                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AUTO,
+        List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser(
+                mIntent,
+                GET_META_DATA | MATCH_DIRECT_BOOT_AUTO | MATCH_SYSTEM_ONLY,
                 mCurrentUserId);
-        if (rInfos == null) {
-            rInfos = Collections.emptyList();
-        }
 
-        ComponentName bestComponent = null;
-        int bestVersion = Integer.MIN_VALUE;
-        boolean bestIsMultiuser = false;
-
-        for (ResolveInfo rInfo : rInfos) {
-            ComponentName component = rInfo.serviceInfo.getComponentName();
-            String packageName = component.getPackageName();
-
-            // check signature
-            try {
-                PackageInfo pInfo = mContext.getPackageManager().getPackageInfo(packageName,
-                        PackageManager.GET_SIGNATURES
-                                | PackageManager.MATCH_DIRECT_BOOT_AUTO);
-                if (!isSignatureMatch(pInfo.signatures, mSignatureSets)) {
-                    Log.w(mTag, packageName + " resolves service " + mAction
-                            + ", but has wrong signature, ignoring");
-                    continue;
-                }
-            } catch (NameNotFoundException e) {
-                Log.wtf(mTag, e);
-                continue;
-            }
-
-            // check metadata
-            Bundle metadata = rInfo.serviceInfo.metaData;
-            int version = Integer.MIN_VALUE;
-            boolean isMultiuser = false;
-            if (metadata != null) {
-                version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
-                isMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
-            }
-
-            if (version > bestVersion) {
-                bestComponent = component;
-                bestVersion = version;
-                bestIsMultiuser = isMultiuser;
+        ServiceInfo bestServiceInfo = ServiceInfo.NONE;
+        for (ResolveInfo resolveInfo : resolveInfos) {
+            ServiceInfo serviceInfo = new ServiceInfo(resolveInfo, mCurrentUserId);
+            if (serviceInfo.compareTo(bestServiceInfo) > 0) {
+                bestServiceInfo = serviceInfo;
             }
         }
 
-        if (D) {
-            Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
-                    (mServicePackageName == null ? ""
-                            : "(" + mServicePackageName + ") "), rInfos.size(),
-                    (bestComponent == null ? "no new best component"
-                            : "new best component: " + bestComponent)));
+        if (forceRebind || !bestServiceInfo.equals(mServiceInfo)) {
+            rebind(bestServiceInfo);
+        }
+    }
+
+    private void rebind(ServiceInfo newServiceInfo) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        if (!mServiceInfo.equals(ServiceInfo.NONE)) {
+            if (D) {
+                Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mServiceInfo);
+            }
+
+            mContext.unbindService(this);
+            mServiceInfo = ServiceInfo.NONE;
         }
 
-        if (bestComponent == null) {
-            Slog.w(mTag, "Odd, no component found for service " + mAction);
-            unbind();
+        mServiceInfo = newServiceInfo;
+        if (mServiceInfo.equals(ServiceInfo.NONE)) {
             return;
         }
 
-        int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
-        boolean alreadyBound = Objects.equals(bestComponent, mBestComponent)
-                && bestVersion == mBestVersion && userId == mBestUserId;
-        if (forceRebind || !alreadyBound) {
-            unbind();
-            bind(bestComponent, bestVersion, userId);
+        Preconditions.checkState(mServiceInfo.component != null);
+
+        if (D) {
+            Log.i(TAG, getLogPrefix() + " binding to " + mServiceInfo);
+        }
+
+        Intent bindIntent = new Intent(mIntent).setComponent(mServiceInfo.component);
+        mContext.bindServiceAsUser(bindIntent, this,
+                BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE,
+                mHandler, UserHandle.of(mServiceInfo.userId));
+    }
+
+    @Override
+    public final void onServiceConnected(ComponentName component, IBinder binder) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        if (D) {
+            Log.i(TAG, getLogPrefix() + " connected to " + component);
+        }
+
+        mBinder = binder;
+        if (mOnBind != null) {
+            runOnBinder(mOnBind);
         }
     }
 
-    private void bind(ComponentName component, int version, int userId) {
+    @Override
+    public final void onServiceDisconnected(ComponentName component) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
-        Intent intent = new Intent(mAction);
-        intent.setComponent(component);
-
-        mBestComponent = component;
-        mBestVersion = version;
-        mBestUserId = userId;
-
-        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
-        mContext.bindServiceAsUser(intent, this,
-                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
-                UserHandle.of(userId));
-    }
-
-    private void unbind() {
-        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
-
-        if (mBestComponent != null) {
-            if (D) Log.d(mTag, "unbinding " + mBestComponent);
-            mContext.unbindService(this);
+        if (D) {
+            Log.i(TAG, getLogPrefix() + " disconnected from " + component);
         }
 
-        mBestComponent = null;
-        mBestVersion = Integer.MIN_VALUE;
-        mBestUserId = UserHandle.USER_NULL;
+        mBinder = null;
+        if (mOnUnbind != null) {
+            mOnUnbind.run();
+        }
+    }
+
+    private void onUserSwitched(@UserIdInt int userId) {
+        mCurrentUserId = userId;
+        onBestServiceChanged(false);
+    }
+
+    private void onUserUnlocked(@UserIdInt int userId) {
+        if (userId == mCurrentUserId) {
+            onBestServiceChanged(false);
+        }
+    }
+
+    private void onPackageChanged(String packageName) {
+        // force a rebind if the changed package was the currently connected package
+        String currentPackageName =
+                mServiceInfo.component != null ? mServiceInfo.component.getPackageName() : null;
+        onBestServiceChanged(packageName.equals(currentPackageName));
     }
 
     /**
@@ -365,26 +388,26 @@
      */
     public final void runOnBinder(BinderRunner runner) {
         runOnHandler(() -> {
-            if (mBestService == null) {
+            if (mBinder == null) {
                 return;
             }
 
             try {
-                runner.run(mBestService);
-            } catch (RuntimeException e) {
-                // the code being run is privileged, but may be outside the system server, and thus
-                // we cannot allow runtime exceptions to crash the system server
-                Log.e(TAG, "exception while while running " + runner + " on " + mBestService
-                        + " from " + this, e);
-            } catch (RemoteException e) {
-                // do nothing
+                runner.run(mBinder);
+            } catch (RuntimeException | RemoteException e) {
+                // binders may propagate some specific non-RemoteExceptions from the other side
+                // through the binder as well - we cannot allow those to crash the system server
+                Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e);
             }
         });
     }
 
     /**
      * Runs the given function synchronously if currently connected, and returns the default value
-     * if not currently connected or if any exception is thrown.
+     * if not currently connected or if any exception is thrown. Do not obtain any locks within the
+     * BlockingBinderRunner, or risk deadlock. The default value will be returned if there is no
+     * service connection when this is run, if a RemoteException occurs, or if the operation times
+     * out.
      *
      * @deprecated Using this function is an indication that your AIDL API is broken. Calls from
      * system server to outside MUST be one-way, and so cannot return any result, and this
@@ -395,13 +418,16 @@
     public final <T> T runOnBinderBlocking(BlockingBinderRunner<T> runner, T defaultValue) {
         try {
             return runOnHandlerBlocking(() -> {
-                if (mBestService == null) {
+                if (mBinder == null) {
                     return defaultValue;
                 }
 
                 try {
-                    return runner.run(mBestService);
-                } catch (RemoteException e) {
+                    return runner.run(mBinder);
+                } catch (RuntimeException | RemoteException e) {
+                    // binders may propagate some specific non-RemoteExceptions from the other side
+                    // through the binder as well - we cannot allow those to crash the system server
+                    Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e);
                     return defaultValue;
                 }
             });
@@ -410,30 +436,6 @@
         }
     }
 
-    @Override
-    public final void onServiceConnected(ComponentName component, IBinder binder) {
-        runOnHandler(() -> {
-            if (D) Log.d(mTag, component + " connected");
-            mBestService = binder;
-            onBind();
-        });
-    }
-
-    @Override
-    public final void onServiceDisconnected(ComponentName component) {
-        runOnHandler(() -> {
-            if (D) Log.d(mTag, component + " disconnected");
-            mBestService = null;
-            onUnbind();
-        });
-    }
-
-    @Override
-    public String toString() {
-        ComponentName bestComponent = mBestComponent;
-        return bestComponent == null ? "null" : bestComponent.toShortString() + "@" + mBestVersion;
-    }
-
     private void runOnHandler(Runnable r) {
         if (Looper.myLooper() == mHandler.getLooper()) {
             r.run();
@@ -467,4 +469,8 @@
             }
         }
     }
+
+    private String getLogPrefix() {
+        return "[" + mIntent.getAction() + "]";
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ac85bf5..0a91f9a 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) {
@@ -371,6 +384,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 +657,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 +1323,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 +1690,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 +1838,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 +2234,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 +3101,7 @@
         r.isForeground = false;
         r.foregroundId = 0;
         r.foregroundNoti = null;
+        r.mAllowWhileInUsePermissionInFgs = false;
 
         // Clear start entries.
         r.clearDeliveredStartsLocked();
@@ -4533,4 +4570,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 00c0b3e..c987dea 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;
@@ -214,6 +215,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PathPermission;
 import android.content.pm.PermissionInfo;
+import android.content.pm.ProcessInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.SELinuxUtil;
@@ -751,67 +753,23 @@
     }
 
     /**
+     * These are the currently running processes for which we have a ProcessInfo.
+     * Note: needs to be static since the permission checking call chain is static.  This
+     * all probably should be refactored into a separate permission checking object.
+     */
+    @GuardedBy("sActiveProcessInfoSelfLocked")
+    static final SparseArray<ProcessInfo> sActiveProcessInfoSelfLocked = new SparseArray<>();
+
+    /**
      * All of the processes we currently have running organized by pid.
      * The keys are the pid running the application.
      *
      * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock!
      */
     final PidMap mPidsSelfLocked = new PidMap();
-    final class PidMap {
+    static final class PidMap {
         private final SparseArray<ProcessRecord> mPidMap = new SparseArray<>();
 
-        /**
-         * Puts the process record in the map.
-         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
-         * method.
-         */
-        void put(ProcessRecord app) {
-            synchronized (this) {
-                mPidMap.put(app.pid, app);
-            }
-            mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController());
-        }
-
-        /**
-         * Removes the process record from the map.
-         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
-         * method.
-         */
-        void remove(ProcessRecord app) {
-            boolean removed = false;
-            synchronized (this) {
-                final ProcessRecord existingApp = mPidMap.get(app.pid);
-                if (existingApp != null && existingApp.startSeq == app.startSeq) {
-                    mPidMap.remove(app.pid);
-                    removed = true;
-                }
-            }
-            if (removed) {
-                mAtmInternal.onProcessUnMapped(app.pid);
-            }
-        }
-
-        /**
-         * Removes the process record from the map if it has a thread.
-         * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
-         * method.
-         */
-        boolean removeIfNoThread(ProcessRecord app) {
-            boolean removed = false;
-            synchronized (this) {
-                final ProcessRecord existingApp = get(app.pid);
-                if (existingApp != null && existingApp.startSeq == app.startSeq
-                        && app.thread == null) {
-                    mPidMap.remove(app.pid);
-                    removed = true;
-                }
-            }
-            if (removed) {
-                mAtmInternal.onProcessUnMapped(app.pid);
-            }
-            return removed;
-        }
-
         ProcessRecord get(int pid) {
             return mPidMap.get(pid);
         }
@@ -831,6 +789,82 @@
         int indexOfKey(int key) {
             return mPidMap.indexOfKey(key);
         }
+
+        void doAddInternal(ProcessRecord app) {
+            mPidMap.put(app.pid, app);
+        }
+
+        boolean doRemoveInternal(ProcessRecord app) {
+            final ProcessRecord existingApp = mPidMap.get(app.pid);
+            if (existingApp != null && existingApp.startSeq == app.startSeq) {
+                mPidMap.remove(app.pid);
+                return true;
+            }
+            return false;
+        }
+
+        boolean doRemoveIfNoThreadInternal(ProcessRecord app) {
+            if (app == null || app.thread != null) {
+                return false;
+            }
+            return doRemoveInternal(app);
+        }
+    }
+
+    /**
+     * Puts the process record in the map.
+     * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+     * method.
+     */
+    void addPidLocked(ProcessRecord app) {
+        synchronized (mPidsSelfLocked) {
+            mPidsSelfLocked.doAddInternal(app);
+        }
+        synchronized (sActiveProcessInfoSelfLocked) {
+            if (app.processInfo != null) {
+                sActiveProcessInfoSelfLocked.put(app.pid, app.processInfo);
+            } else {
+                sActiveProcessInfoSelfLocked.remove(app.pid);
+            }
+        }
+        mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController());
+    }
+
+    /**
+     * Removes the process record from the map.
+     * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+     * method.
+     */
+    void removePidLocked(ProcessRecord app) {
+        final boolean removed;
+        synchronized (mPidsSelfLocked) {
+            removed = mPidsSelfLocked.doRemoveInternal(app);
+        }
+        if (removed) {
+            synchronized (sActiveProcessInfoSelfLocked) {
+                sActiveProcessInfoSelfLocked.remove(app.pid);
+            }
+            mAtmInternal.onProcessUnMapped(app.pid);
+        }
+    }
+
+    /**
+     * Removes the process record from the map if it doesn't have a thread.
+     * <p>NOTE: Callers should avoid acquiring the mPidsSelfLocked lock before calling this
+     * method.
+     */
+    boolean removePidIfNoThread(ProcessRecord app) {
+        final boolean removed;
+        synchronized (mPidsSelfLocked) {
+            removed = mPidsSelfLocked.doRemoveIfNoThreadInternal(app);
+        }
+        if (removed) {
+            synchronized (sActiveProcessInfoSelfLocked) {
+                sActiveProcessInfoSelfLocked.remove(app.pid);
+            }
+            mAtmInternal.onProcessUnMapped(app.pid);
+        }
+        return removed;
     }
 
     /**
@@ -2061,7 +2095,7 @@
                 app.getWindowProcessController().setPid(MY_PID);
                 app.maxAdj = ProcessList.SYSTEM_ADJ;
                 app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
-                mPidsSelfLocked.put(app);
+                addPidLocked(app);
                 mProcessList.updateLruProcessLocked(app, false, null);
                 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
             }
@@ -4723,7 +4757,7 @@
     @GuardedBy("this")
     private final void processStartTimedOutLocked(ProcessRecord app) {
         final int pid = app.pid;
-        boolean gone = mPidsSelfLocked.removeIfNoThread(app);
+        boolean gone = removePidIfNoThread(app);
 
         if (gone) {
             Slog.w(TAG, "Process " + app + " failed to attach");
@@ -4796,7 +4830,7 @@
                 // If there is already an app occupying that pid that hasn't been cleaned up
                 cleanUpApplicationRecordLocked(app, false, false, -1,
                             true /*replacingPid*/);
-                mPidsSelfLocked.remove(app);
+                removePidLocked(app);
                 app = null;
             }
         } else {
@@ -5746,7 +5780,8 @@
             if (uidRec == null || uidRec.idle) {
                 return false;
             }
-            return uidRec.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+            return uidRec.getCurProcState()
+                    <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
         }
     }
 
@@ -5896,6 +5931,21 @@
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
         }
+        // If there is an explicit permission being checked, and this is coming from a process
+        // that has been denied access to that permission, then just deny.  Ultimately this may
+        // not be quite right -- it means that even if the caller would have access for another
+        // reason (such as being the owner of the component it is trying to access), it would still
+        // fail.  This also means the system and root uids would be able to deny themselves
+        // access to permissions, which...  well okay. ¯\_(ツ)_/¯
+        if (permission != null) {
+            synchronized (sActiveProcessInfoSelfLocked) {
+                ProcessInfo procInfo = sActiveProcessInfoSelfLocked.get(pid);
+                if (procInfo != null && procInfo.deniedPermissions != null
+                        && procInfo.deniedPermissions.contains(permission)) {
+                    return PackageManager.PERMISSION_DENIED;
+                }
+            }
+        }
         return ActivityManager.checkComponentPermission(permission, uid,
                 owningUid, exported);
     }
@@ -14367,7 +14417,7 @@
             return true;
         } else if (app.pid > 0 && app.pid != MY_PID) {
             // Goodbye!
-            mPidsSelfLocked.remove(app);
+            removePidLocked(app);
             mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
             if (app.isolated) {
@@ -19040,6 +19090,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) {
@@ -19594,4 +19666,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/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/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index fa55701..a03f0bb 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -108,6 +108,21 @@
         sDeviceConfigEntries.add(new DeviceConfigEntry(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL,
                 WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class));
+        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT,
+                WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class));
+        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_OPACITY,
+                WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, int.class));
+        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_NEW_MAGNIFIER,
+                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, boolean.class));
+        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ZOOM_FACTOR,
+                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, float.class));
+        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO,
+                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class));
         // add other device configs here...
     }
 
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..e9d6491 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
@@ -73,6 +74,7 @@
 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;
@@ -129,13 +131,27 @@
      * 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;
+
+    /**
      * 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
@@ -1460,22 +1477,13 @@
                 }
             }
 
-            if (s.isForeground) {
+            if (s.isForeground && s.mAllowWhileInUsePermissionInFgs) {
                 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) {
-                    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;
-                }
+                capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
+                        | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
             }
 
             ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
@@ -1513,13 +1521,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 +1953,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 +2195,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 +2514,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 4a89845..38cb501 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1564,7 +1564,7 @@
         long startTime = SystemClock.uptimeMillis();
         if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
             checkSlow(startTime, "startProcess: removing from pids map");
-            mService.mPidsSelfLocked.remove(app);
+            mService.removePidLocked(app);
             mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             checkSlow(startTime, "startProcess: done removing from pids map");
             app.setPid(0);
@@ -1609,10 +1609,28 @@
                 } catch (RemoteException e) {
                     throw e.rethrowAsRuntimeException();
                 }
+
+                // Remove any gids needed if the process has been denied permissions.
+                // NOTE: eventually we should probably have the package manager pre-compute
+                // this for us?
+                if (app.processInfo != null && app.processInfo.deniedPermissions != null) {
+                    for (int i = app.processInfo.deniedPermissions.size() - 1; i >= 0; i--) {
+                        int[] denyGids = mService.mPackageManagerInt.getPermissionGids(
+                                app.processInfo.deniedPermissions.valueAt(i), app.userId);
+                        if (denyGids != null) {
+                            for (int gid : denyGids) {
+                                permGids = ArrayUtils.removeInt(permGids, gid);
+                            }
+                        }
+                    }
+                }
+
                 int numGids = 3;
-                if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
+                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
@@ -1626,8 +1644,14 @@
                 gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
                 gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
                 gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
+
                 if (numGids > 3) {
-                    gids[3] = Process.SDCARD_RW_GID;
+                    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
@@ -2311,7 +2335,7 @@
             mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                     true /*replacingPid*/);
         }
-        mService.mPidsSelfLocked.put(app);
+        mService.addPidLocked(app);
         synchronized (mService.mPidsSelfLocked) {
             if (!procAttached) {
                 Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
@@ -2492,7 +2516,7 @@
                 .pendingStart)) {
             int pid = app.pid;
             if (pid > 0) {
-                mService.mPidsSelfLocked.remove(app);
+                mService.removePidLocked(app);
                 mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
                 mService.mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
                 if (app.isolated) {
@@ -3945,4 +3969,3 @@
         }
     };
 }
-
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 156466c..1e2dd2d 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -35,6 +35,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ProcessInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.VersionedPackage;
 import android.content.res.CompatibilityInfo;
@@ -84,6 +85,7 @@
 
     private final ActivityManagerService mService; // where we came from
     final ApplicationInfo info; // all about the first app in the process
+    final ProcessInfo processInfo; // if non-null, process-specific manifest info
     final boolean isolated;     // true if this is a special isolated process
     final boolean appZygote;    // true if this is forked from the app zygote
     final int uid;              // uid of process; may be different from 'info' if isolated
@@ -161,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
@@ -603,6 +607,13 @@
             int _uid) {
         mService = _service;
         info = _info;
+        if (_service.mPackageManagerInt != null) {
+            ArrayMap<String, ProcessInfo> processes =
+                    _service.mPackageManagerInt.getProcessesForUid(_uid);
+            processInfo = processes != null ? processes.get(_processName) : null;
+        } else {
+            processInfo = null;
+        }
         isolated = _info.uid != _uid;
         appZygote = (UserHandle.getAppId(_uid) >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID
                 && UserHandle.getAppId(_uid) <= Process.LAST_APP_ZYGOTE_ISOLATED_UID);
@@ -614,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..62596de 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;
@@ -288,6 +291,8 @@
     @GuardedBy("this")
     private SparseArray<List<Integer>> mSwitchOpToOps;
 
+    private ActivityManagerInternal mActivityManagerInternal;
+
     /**
      * An unsynchronized pool of {@link OpEventProxyInfo} objects.
      */
@@ -423,7 +428,7 @@
     final Constants mConstants;
 
     @VisibleForTesting
-    static final class UidState {
+    final class UidState {
         public final int uid;
 
         public int state = UID_STATE_CACHED;
@@ -431,6 +436,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 +446,8 @@
         public SparseBooleanArray foregroundOps;
         public boolean hasForegroundWatchers;
 
+        public long lastTimeShowDebugToast;
+
         public UidState(int uid) {
             this.uid = uid;
         }
@@ -457,7 +466,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 +478,28 @@
                         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 {
+                                maybeShowWhileInUseDebugToast(op, mode);
+                                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 +507,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 +576,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 > 600000) {
+                lastTimeShowDebugToast = now;
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        ActivityManagerInternal::showWhileInUseDebugToast,
+                        mActivityManagerInternal, uid, op, mode));
+            }
+        }
     }
 
     final static class Ops extends SparseArray<Op> {
@@ -1476,6 +1539,7 @@
                         }
                     });
         }
+        mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
     }
 
     public void packageRemoved(int uid, String packageName) {
@@ -1760,6 +1824,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 +3066,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 +3288,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 +3324,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 +4565,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 +4697,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 +4760,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 +5578,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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 73ec43f..8f6bd21 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7041,6 +7041,26 @@
         }
     }
 
+    /** see AudioPolicy.setUserIdDeviceAffinity() */
+    public int setUserIdDeviceAffinity(IAudioPolicyCallback pcb, int userId,
+            @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
+        if (DEBUG_AP) {
+            Log.d(TAG, "setUserIdDeviceAffinity for " + pcb.asBinder() + " user:" + userId);
+        }
+
+        synchronized (mAudioPolicies) {
+            final AudioPolicyProxy app =
+                    checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
+            if (app == null) {
+                return AudioManager.ERROR;
+            }
+            if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
+                return AudioManager.ERROR;
+            }
+            return app.setUserIdDeviceAffinities(userId, deviceTypes, deviceAddresses);
+        }
+    }
+
     /** see AudioPolicy.removeUidDeviceAffinity() */
     public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
         if (DEBUG_AP) {
@@ -7056,6 +7076,22 @@
         }
     }
 
+    /** see AudioPolicy.removeUserIdDeviceAffinity() */
+    public int removeUserIdDeviceAffinity(IAudioPolicyCallback pcb, int userId) {
+        if (DEBUG_AP) {
+            Log.d(TAG, "removeUserIdDeviceAffinity for " + pcb.asBinder()
+                    + " userId:" + userId);
+        }
+        synchronized (mAudioPolicies) {
+            final AudioPolicyProxy app =
+                    checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
+            if (app == null) {
+                return AudioManager.ERROR;
+            }
+            return app.removeUserIdDeviceAffinities(userId);
+        }
+    }
+
     public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
         if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
                 + " policy " +  pcb.asBinder());
@@ -7291,6 +7327,9 @@
         final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
                 new HashMap<Integer, AudioDeviceArray>();
 
+        final HashMap<Integer, AudioDeviceArray> mUserIdDeviceAffinities =
+                new HashMap<>();
+
         final IMediaProjection mProjection;
         private final class UnregisterOnStopCallback extends IMediaProjectionCallback.Stub {
             public void onStop() {
@@ -7482,6 +7521,45 @@
             return AudioManager.ERROR;
         }
 
+        int setUserIdDeviceAffinities(int userId,
+                @NonNull int[] types, @NonNull String[] addresses) {
+            final Integer UserId = new Integer(userId);
+            int res;
+            if (mUserIdDeviceAffinities.remove(UserId) != null) {
+                final long identity = Binder.clearCallingIdentity();
+                res = AudioSystem.removeUserIdDeviceAffinities(UserId);
+                Binder.restoreCallingIdentity(identity);
+                if (res != AudioSystem.SUCCESS) {
+                    Log.e(TAG, "AudioSystem. removeUserIdDeviceAffinities("
+                            + UserId + ") failed, "
+                            + " cannot call AudioSystem.setUserIdDeviceAffinities");
+                    return AudioManager.ERROR;
+                }
+            }
+            final long identity = Binder.clearCallingIdentity();
+            res = AudioSystem.setUserIdDeviceAffinities(userId, types, addresses);
+            Binder.restoreCallingIdentity(identity);
+            if (res == AudioSystem.SUCCESS) {
+                mUserIdDeviceAffinities.put(UserId, new AudioDeviceArray(types, addresses));
+                return AudioManager.SUCCESS;
+            }
+            Log.e(TAG, "AudioSystem.setUserIdDeviceAffinities(" + userId + ") failed");
+            return AudioManager.ERROR;
+        }
+
+        int removeUserIdDeviceAffinities(int userId) {
+            if (mUserIdDeviceAffinities.remove(new Integer(userId)) != null) {
+                final long identity = Binder.clearCallingIdentity();
+                final int res = AudioSystem.removeUserIdDeviceAffinities(userId);
+                Binder.restoreCallingIdentity(identity);
+                if (res == AudioSystem.SUCCESS) {
+                    return AudioManager.SUCCESS;
+                }
+            }
+            Log.e(TAG, "AudioSystem.removeUserIdDeviceAffinities failed");
+            return AudioManager.ERROR;
+        }
+
         /** @return human readable debug informations summarizing the state of the object. */
         public String toLogFriendlyString() {
             String textDump = super.toLogFriendlyString();
diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
index 299cb66..4fb6607 100644
--- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
+++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java
@@ -82,12 +82,14 @@
     }
 
     /**
-     * Convert events in the ring buffer to protos and add to the given list
+     * Convert events in the ring buffer to a list of IpConnectivityEvent protos
      */
-    public synchronized void listEventsAsProto(List<IpConnectivityEvent> out) {
+    public synchronized List<IpConnectivityEvent> listEventsAsProto() {
+        List<IpConnectivityEvent> list = new ArrayList<>();
         for (DefaultNetworkEvent ev : mEventsLog.toArray()) {
-            out.add(IpConnectivityEventBuilder.toProto(ev));
+            list.add(IpConnectivityEventBuilder.toProto(ev));
         }
+        return list;
     }
 
     public synchronized void flushEvents(List<IpConnectivityEvent> out) {
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index 1337a93..2c06d82 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -244,9 +244,9 @@
     private List<IpConnectivityEvent> listEventsAsProtos() {
         final List<IpConnectivityEvent> events = IpConnectivityEventBuilder.toProto(getEvents());
         if (mNetdListener != null) {
-            mNetdListener.listAsProtos(events);
+            events.addAll(mNetdListener.listAsProtos());
         }
-        mDefaultNetworkMetrics.listEventsAsProto(events);
+        events.addAll(mDefaultNetworkMetrics.listEventsAsProto());
         return events;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 0d31051..f2892cc 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -367,18 +367,20 @@
     }
 
     /**
-     * Convert events in the buffer to protos and add to the given list
+     * Convert events in the buffer to a list of IpConnectivityEvent protos
      */
-    public synchronized void listAsProtos(List<IpConnectivityEvent> out) {
+    public synchronized List<IpConnectivityEvent> listAsProtos() {
+        List<IpConnectivityEvent> list = new ArrayList<>();
         for (int i = 0; i < mNetworkMetrics.size(); i++) {
-            out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics));
+            list.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics));
         }
         for (int i = 0; i < mNetworkMetrics.size(); i++) {
-            out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics));
+            list.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics));
         }
         for (int i = 0; i < mWakeupStats.size(); i++) {
-            out.add(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i)));
+            list.add(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i)));
         }
+        return list;
     }
 
     private long getTransports(int netId) {
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/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 1f17f9f..7e8fe3a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -41,8 +41,8 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
-import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -164,7 +164,7 @@
 
     private final class LocalDisplayDevice extends DisplayDevice {
         private final long mPhysicalDisplayId;
-        private final Light mBacklight;
+        private final LogicalLight mBacklight;
         private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
         private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
         private final boolean mIsInternal;
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..214dcc0 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;
@@ -49,6 +48,7 @@
 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 +74,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;
@@ -161,6 +172,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 {
@@ -238,7 +251,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));
@@ -258,6 +271,16 @@
                             + result.getEffect()
                             + " due to "
                             + result.getRule());
+
+            StatsLog.write(
+                    StatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
+                    packageName,
+                    appCert,
+                    appInstallMetadata.getVersionCode(),
+                    installerPackageName,
+                    getLoggingResponse(result),
+                    isCausedByAppCertRule(result),
+                    isCausedByInstallerRule(result));
             mPackageManagerInternal.setIntegrityVerificationResult(
                     verificationId,
                     result.getEffect() == IntegrityCheckResult.Effect.ALLOW
@@ -570,6 +593,26 @@
         }
     }
 
+    private static int getLoggingResponse(IntegrityCheckResult result) {
+        if (result.getEffect() == IntegrityCheckResult.Effect.DENY) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED;
+        } else if (result.getRule() != null) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED;
+        } else {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED;
+        }
+    }
+
+    private static boolean isCausedByAppCertRule(IntegrityCheckResult result) {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
+    private static boolean isCausedByInstallerRule(IntegrityCheckResult result) {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
     private List<String> getAllowedRuleProviders() {
         return Arrays.asList(mContext.getResources().getStringArray(
                 R.array.config_integrityRuleProviderPackages));
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..1a6b3d8 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(
@@ -89,14 +89,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 +108,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 +117,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..66537ff 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -22,7 +22,6 @@
 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;
 
@@ -35,8 +34,6 @@
  */
 final class RuleEvaluator {
 
-    private static final String TAG = "RuleEvaluator";
-
     /**
      * Match the list of rules against an app install metadata.
      *
@@ -53,7 +50,7 @@
             List<Rule> rules, AppInstallMetadata appInstallMetadata) {
         List<Rule> matchedRules = new ArrayList<>();
         for (Rule rule : rules) {
-            if (rule.getFormula().isSatisfied(appInstallMetadata)) {
+            if (rule.getFormula().matches(appInstallMetadata)) {
                 matchedRules.add(rule);
             }
         }
@@ -71,8 +68,7 @@
                 case FORCE_ALLOW:
                     return IntegrityCheckResult.allow(rule);
                 default:
-                    Slog.e(TAG, "Matched an unknown effect rule: " + rule);
-                    return IntegrityCheckResult.allow();
+                    throw new IllegalArgumentException("Matched an unknown effect rule: " + rule);
             }
         }
         return denied ? IntegrityCheckResult.deny(denyRule) : 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/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/lights/LightsManager.java b/services/core/java/com/android/server/lights/LightsManager.java
index be20a44..521913a 100644
--- a/services/core/java/com/android/server/lights/LightsManager.java
+++ b/services/core/java/com/android/server/lights/LightsManager.java
@@ -29,5 +29,8 @@
     public static final int LIGHT_ID_WIFI = Type.WIFI;
     public static final int LIGHT_ID_COUNT = Type.COUNT;
 
-    public abstract Light getLight(int id);
+    /**
+     * Returns the logical light with the given type.
+     */
+    public abstract LogicalLight getLight(int id);
 }
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 8e6e1d6..5683e69 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -15,32 +15,223 @@
 
 package com.android.server.lights;
 
+import android.Manifest;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
+import android.hardware.light.HwLight;
+import android.hardware.light.HwLightState;
+import android.hardware.light.ILights;
+import android.hardware.lights.ILightsManager;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
+import android.os.Looper;
 import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.Trace;
 import android.provider.Settings;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.SurfaceControl;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 public class LightsService extends SystemService {
     static final String TAG = "LightsService";
     static final boolean DEBUG = false;
 
-    final LightImpl mLights[] = new LightImpl[LightsManager.LIGHT_ID_COUNT];
+    private LightImpl[] mLights = null;
+    private SparseArray<LightImpl> mLightsById = null;
 
-    private final class LightImpl extends Light {
+    private ILights mVintfLights = null;
 
+    @VisibleForTesting
+    final LightsManagerBinderService mManagerService;
+
+    private Handler mH;
+
+    private final class LightsManagerBinderService extends ILightsManager.Stub {
+
+        private final class Session {
+            final IBinder mToken;
+            final SparseArray<LightState> mRequests = new SparseArray<>();
+
+            Session(IBinder token) {
+                mToken = token;
+            }
+
+            void setRequest(int lightId, LightState state) {
+                if (state != null) {
+                    mRequests.put(lightId, state);
+                } else {
+                    mRequests.remove(lightId);
+                }
+            }
+        }
+
+        @GuardedBy("LightsService.this")
+        private final List<Session> mSessions = new ArrayList<>();
+
+        /**
+         * Returns the lights available for apps to control on the device. Only lights that aren't
+         * reserved for system use are available to apps.
+         */
+        @Override
+        public List<Light> getLights() {
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
+                    "getLights requires CONTROL_DEVICE_LIGHTS_PERMISSION");
+
+            synchronized (LightsService.this) {
+                final List<Light> lights = new ArrayList<Light>();
+                for (int i = 0; i < mLightsById.size(); i++) {
+                    HwLight hwLight = mLightsById.valueAt(i).getHwLight();
+                    if (!isSystemLight(hwLight)) {
+                        lights.add(new Light(hwLight.id, hwLight.ordinal, hwLight.type));
+                    }
+                }
+                return lights;
+            }
+        }
+
+        /**
+         * Updates the set of light requests for {@param token} with additions and removals from
+         * {@param lightIds} and {@param lightStates}.
+         *
+         * <p>Null values mean that the request should be removed, and the light turned off if it
+         * is not being used by anything else.
+         */
+        @Override
+        public void setLightStates(IBinder token, int[] lightIds, LightState[] lightStates) {
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
+                    "setLightStates requires CONTROL_DEVICE_LIGHTS permission");
+            Preconditions.checkState(lightIds.length == lightStates.length);
+
+            synchronized (LightsService.this) {
+                Session session = getSessionLocked(Preconditions.checkNotNull(token));
+                Preconditions.checkState(session != null, "not registered");
+
+                checkRequestIsValid(lightIds);
+
+                for (int i = 0; i < lightIds.length; i++) {
+                    session.setRequest(lightIds[i], lightStates[i]);
+                }
+                invalidateLightStatesLocked();
+            }
+        }
+
+        @Override
+        public @Nullable LightState getLightState(int lightId) {
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
+                    "getLightState(@TestApi) requires CONTROL_DEVICE_LIGHTS permission");
+
+            synchronized (LightsService.this) {
+                final LightImpl light = mLightsById.get(lightId);
+                if (light == null || isSystemLight(light.getHwLight())) {
+                    throw new IllegalArgumentException("Invalid light: " + lightId);
+                }
+                return new LightState(light.getColor());
+            }
+        }
+
+        @Override
+        public void openSession(IBinder token) {
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
+                    "openSession requires CONTROL_DEVICE_LIGHTS permission");
+            Preconditions.checkNotNull(token);
+
+            synchronized (LightsService.this) {
+                Preconditions.checkState(getSessionLocked(token) == null, "already registered");
+                try {
+                    token.linkToDeath(() -> closeSessionInternal(token), 0);
+                    mSessions.add(new Session(token));
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Couldn't open session, client already died" , e);
+                    throw new IllegalArgumentException("Client is already dead.");
+                }
+            }
+        }
+
+        @Override
+        public void closeSession(IBinder token) {
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.CONTROL_DEVICE_LIGHTS,
+                    "closeSession requires CONTROL_DEVICE_LIGHTS permission");
+            Preconditions.checkNotNull(token);
+            closeSessionInternal(token);
+        }
+
+        private void closeSessionInternal(IBinder token) {
+            synchronized (LightsService.this) {
+                final Session session = getSessionLocked(token);
+                if (session != null) {
+                    mSessions.remove(session);
+                    invalidateLightStatesLocked();
+                }
+            }
+        }
+
+        private void checkRequestIsValid(int[] lightIds) {
+            for (int i = 0; i < lightIds.length; i++) {
+                final LightImpl light = mLightsById.get(lightIds[i]);
+                final HwLight hwLight = light.getHwLight();
+                Preconditions.checkState(light != null && !isSystemLight(hwLight),
+                        "invalid lightId " + hwLight.id);
+            }
+        }
+
+        /**
+         * Apply light state requests for all light IDs.
+         *
+         * <p>In case of conflict, the session that started earliest wins.
+         */
+        private void invalidateLightStatesLocked() {
+            final Map<Integer, LightState> states = new HashMap<>();
+            for (int i = mSessions.size() - 1; i >= 0; i--) {
+                SparseArray<LightState> requests = mSessions.get(i).mRequests;
+                for (int j = 0; j < requests.size(); j++) {
+                    states.put(requests.keyAt(j), requests.valueAt(j));
+                }
+            }
+            for (int i = 0; i < mLightsById.size(); i++) {
+                LightImpl light = mLightsById.valueAt(i);
+                HwLight hwLight = light.getHwLight();
+                if (!isSystemLight(hwLight)) {
+                    LightState state = states.get(hwLight.id);
+                    if (state != null) {
+                        light.setColor(state.getColor());
+                    } else {
+                        light.turnOff();
+                    }
+                }
+            }
+        }
+
+        private @Nullable Session getSessionLocked(IBinder token) {
+            for (int i = 0; i < mSessions.size(); i++) {
+                if (token.equals(mSessions.get(i).mToken)) {
+                    return mSessions.get(i);
+                }
+            }
+            return null;
+        }
+    }
+
+    private final class LightImpl extends LogicalLight {
         private final IBinder mDisplayToken;
         private final int mSurfaceControlMaximumBrightness;
 
-        private LightImpl(Context context, int id) {
-            mId = id;
+        private LightImpl(Context context, HwLight hwLight) {
+            mHwLight = hwLight;
             mDisplayToken = SurfaceControl.getInternalDisplayToken();
             final boolean brightnessSupport = SurfaceControl.getDisplayBrightnessSupport(
                     mDisplayToken);
@@ -78,8 +269,8 @@
             synchronized (this) {
                 // LOW_PERSISTENCE cannot be manually set
                 if (brightnessMode == BRIGHTNESS_MODE_LOW_PERSISTENCE) {
-                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mId +
-                            ": brightness=0x" + Integer.toHexString(brightness));
+                    Slog.w(TAG, "setBrightness with LOW_PERSISTENCE unexpected #" + mHwLight.id
+                            + ": brightness=0x" + Integer.toHexString(brightness));
                     return;
                 }
                 // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
@@ -138,7 +329,7 @@
                     setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000,
                             BRIGHTNESS_MODE_USER);
                     mColor = 0;
-                    mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
+                    mH.postDelayed(this::stopFlashing, onMS);
                 }
             }
         }
@@ -185,8 +376,10 @@
 
             if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS ||
                     offMS != mOffMS || mBrightnessMode != brightnessMode) {
-                if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#"
-                        + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
+                if (DEBUG) {
+                    Slog.v(TAG, "setLight #" + mHwLight.id + ": color=#"
+                            + Integer.toHexString(color) + ": brightnessMode=" + brightnessMode);
+                }
                 mInitialized = true;
                 mLastColor = mColor;
                 mColor = color;
@@ -194,10 +387,31 @@
                 mOnMS = onMS;
                 mOffMS = offMS;
                 mBrightnessMode = brightnessMode;
-                Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLight(" + mId + ", 0x"
-                        + Integer.toHexString(color) + ")");
+                setLightUnchecked(color, mode, onMS, offMS, brightnessMode);
+            }
+        }
+
+        private void setLightUnchecked(int color, int mode, int onMS, int offMS,
+                int brightnessMode) {
+            Trace.traceBegin(Trace.TRACE_TAG_POWER, "setLightState(" + mHwLight.id + ", 0x"
+                    + Integer.toHexString(color) + ")");
+            if (mVintfLights != null) {
+                HwLightState lightState = new HwLightState();
+                lightState.color = color;
+                lightState.flashMode = (byte) mode;
+                lightState.flashOnMs = onMS;
+                lightState.flashOffMs = offMS;
+                lightState.brightnessMode = (byte) brightnessMode;
                 try {
-                    setLight_native(mId, color, mode, onMS, offMS, brightnessMode);
+                    mVintfLights.setLightState(mHwLight.id, lightState);
+                } catch (RemoteException | UnsupportedOperationException ex) {
+                    Slog.e(TAG, "Failed issuing setLightState", ex);
+                } finally {
+                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
+                }
+            } else {
+                try {
+                    setLight_native(mHwLight.id, color, mode, onMS, offMS, brightnessMode);
                 } finally {
                     Trace.traceEnd(Trace.TRACE_TAG_POWER);
                 }
@@ -208,7 +422,15 @@
             return mVrModeEnabled && mUseLowPersistenceForVR;
         }
 
-        private int mId;
+        private HwLight getHwLight() {
+            return mHwLight;
+        }
+
+        private int getColor() {
+            return mColor;
+        }
+
+        private HwLight mHwLight;
         private int mColor;
         private int mMode;
         private int mOnMS;
@@ -223,16 +445,59 @@
     }
 
     public LightsService(Context context) {
-        super(context);
+        this(context,
+                ILights.Stub.asInterface(
+                        ServiceManager.getService("android.hardware.light.ILights/default")),
+                Looper.myLooper());
+    }
 
-        for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
-            mLights[i] = new LightImpl(context, i);
+    @VisibleForTesting
+    LightsService(Context context, ILights service, Looper looper) {
+        super(context);
+        mH = new Handler(looper);
+        mVintfLights = service;
+        mManagerService = new LightsManagerBinderService();
+        populateAvailableLights(context);
+    }
+
+    private void populateAvailableLights(Context context) {
+        mLights = new LightImpl[LightsManager.LIGHT_ID_COUNT];
+        mLightsById = new SparseArray<>();
+
+        if (mVintfLights != null) {
+            try {
+                for (HwLight availableLight : mVintfLights.getLights()) {
+                    LightImpl light = new LightImpl(context, availableLight);
+                    int type = (int) availableLight.type;
+                    if (0 <= type && type < mLights.length && mLights[type] == null) {
+                        mLights[type] = light;
+                    }
+                    mLightsById.put(availableLight.id, light);
+                }
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Unable to get lights for initialization", ex);
+            }
+        }
+
+        // In the case where only the old HAL is available, all lights will be initialized here
+        for (int i = 0; i < mLights.length; i++) {
+            if (mLights[i] == null) {
+                // The ordinal can be anything if there is only 1 light of each type. Set it to 1.
+                HwLight light = new HwLight();
+                light.id = (byte) i;
+                light.ordinal = 1;
+                light.type = (byte) i;
+
+                mLights[i] = new LightImpl(context, light);
+                mLightsById.put(i, mLights[i]);
+            }
         }
     }
 
     @Override
     public void onStart() {
         publishLocalService(LightsManager.class, mService);
+        publishBinderService(Context.LIGHTS_SERVICE, mManagerService);
     }
 
     @Override
@@ -249,22 +514,25 @@
 
     private final LightsManager mService = new LightsManager() {
         @Override
-        public Light getLight(int id) {
-            if (0 <= id && id < LIGHT_ID_COUNT) {
-                return mLights[id];
+        public LogicalLight getLight(int lightType) {
+            if (mLights != null && 0 <= lightType && lightType < mLights.length) {
+                return mLights[lightType];
             } else {
                 return null;
             }
         }
     };
 
-    private Handler mH = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            LightImpl light = (LightImpl)msg.obj;
-            light.stopFlashing();
-        }
-    };
+    /**
+     * Returns whether a light is system-use-only or should be accessible to
+     * applications using the {@link android.hardware.lights.LightsManager} API.
+     */
+    private static boolean isSystemLight(HwLight light) {
+        // LIGHT_ID_COUNT comes from the 2.0 HIDL HAL and only contains system
+        // lights. Newly added lights will be made available via the
+        // LightsManager API.
+        return 0 <= light.type && light.type < LightsManager.LIGHT_ID_COUNT;
+    }
 
     static native void setLight_native(int light, int color, int mode,
             int onMS, int offMS, int brightnessMode);
diff --git a/services/core/java/com/android/server/lights/Light.java b/services/core/java/com/android/server/lights/LogicalLight.java
similarity index 74%
rename from services/core/java/com/android/server/lights/Light.java
rename to services/core/java/com/android/server/lights/LogicalLight.java
index 998c7c6..33dfbb4 100644
--- a/services/core/java/com/android/server/lights/Light.java
+++ b/services/core/java/com/android/server/lights/LogicalLight.java
@@ -19,9 +19,24 @@
 import android.hardware.light.V2_0.Brightness;
 import android.hardware.light.V2_0.Flash;
 
-public abstract class Light {
+/**
+ * Allow control over a logical light of a given type. The mapping of logical lights to physical
+ * lights is HAL implementation-dependent.
+ */
+public abstract class LogicalLight {
+    /**
+     * Keep the light steady on or off.
+     */
     public static final int LIGHT_FLASH_NONE = Flash.NONE;
+
+    /**
+     * Flash the light at specified rate.
+     */
     public static final int LIGHT_FLASH_TIMED = Flash.TIMED;
+
+    /**
+     * Flash the light using hardware assist.
+     */
     public static final int LIGHT_FLASH_HARDWARE = Flash.HARDWARE;
 
     /**
@@ -55,10 +70,33 @@
      */
     public abstract void setBrightnessFloat(float brightness);
 
+    /**
+     * Set the color of a light.
+     */
     public abstract void setColor(int color);
+
+    /**
+     * Set the color of a light and control flashing.
+     */
     public abstract void setFlashing(int color, int mode, int onMS, int offMS);
+
+    /**
+     * Pulses the light.
+     */
     public abstract void pulse();
+
+    /**
+     * Pulses the light with a specified color for a specified duration.
+     */
     public abstract void pulse(int color, int onMS);
+
+    /**
+     * Turns off the light.
+     */
     public abstract void turnOff();
+
+    /**
+     * Set the VR mode of a display.
+     */
     public abstract void setVrMode(boolean enabled);
 }
diff --git a/services/core/java/com/android/server/lights/OWNERS b/services/core/java/com/android/server/lights/OWNERS
index c7c6d56..0e795b9 100644
--- a/services/core/java/com/android/server/lights/OWNERS
+++ b/services/core/java/com/android/server/lights/OWNERS
@@ -1,2 +1,3 @@
 michaelwr@google.com
-dangittik@google.com
+santoscordon@google.com
+flc@google.com
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/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
deleted file mode 100644
index 80ab790..0000000
--- a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.location;
-
-import android.content.Context;
-import android.hardware.location.ActivityRecognitionHardware;
-import android.hardware.location.IActivityRecognitionHardwareClient;
-import android.hardware.location.IActivityRecognitionHardwareWatcher;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.server.FgThread;
-import com.android.server.ServiceWatcher;
-
-/**
- * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
- *
- * @hide
- */
-public class ActivityRecognitionProxy {
-
-    private static final String TAG = "ActivityRecognitionProxy";
-
-    /**
-     * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
-     *
-     * @return An instance of the proxy if it could be bound, null otherwise.
-     */
-    public static ActivityRecognitionProxy createAndBind(
-            Context context,
-            boolean activityRecognitionHardwareIsSupported,
-            ActivityRecognitionHardware activityRecognitionHardware,
-            int overlaySwitchResId,
-            int defaultServicePackageNameResId,
-            int initialPackageNameResId) {
-        ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
-                context,
-                activityRecognitionHardwareIsSupported,
-                activityRecognitionHardware,
-                overlaySwitchResId,
-                defaultServicePackageNameResId,
-                initialPackageNameResId);
-
-        if (activityRecognitionProxy.mServiceWatcher.start()) {
-            return activityRecognitionProxy;
-        } else {
-            return null;
-        }
-    }
-
-    private final ServiceWatcher mServiceWatcher;
-    private final boolean mIsSupported;
-    private final ActivityRecognitionHardware mInstance;
-
-    private ActivityRecognitionProxy(
-            Context context,
-            boolean activityRecognitionHardwareIsSupported,
-            ActivityRecognitionHardware activityRecognitionHardware,
-            int overlaySwitchResId,
-            int defaultServicePackageNameResId,
-            int initialPackageNameResId) {
-        mIsSupported = activityRecognitionHardwareIsSupported;
-        mInstance = activityRecognitionHardware;
-
-        mServiceWatcher = new ServiceWatcher(
-                context,
-                TAG,
-                "com.android.location.service.ActivityRecognitionProvider",
-                overlaySwitchResId,
-                defaultServicePackageNameResId,
-                initialPackageNameResId,
-                FgThread.getHandler()) {
-            @Override
-            protected void onBind() {
-                runOnBinder(ActivityRecognitionProxy.this::initializeService);
-            }
-        };
-    }
-
-    private void initializeService(IBinder binder) {
-        try {
-            String descriptor = binder.getInterfaceDescriptor();
-
-            if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(
-                    descriptor)) {
-                IActivityRecognitionHardwareWatcher watcher =
-                        IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
-                if (mInstance != null) {
-                    watcher.onInstanceChanged(mInstance);
-                }
-            } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
-                    .equals(descriptor)) {
-                IActivityRecognitionHardwareClient client =
-                        IActivityRecognitionHardwareClient.Stub.asInterface(binder);
-                client.onAvailabilityChanged(mIsSupported, mInstance);
-            } else {
-                Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, e);
-        }
-    }
-}
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/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index e6f0ed9..536f95a 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.location.Address;
 import android.location.GeocoderParams;
@@ -28,40 +29,38 @@
 
 /**
  * Proxy for IGeocodeProvider implementations.
+ *
+ * @hide
  */
 public class GeocoderProxy {
-    private static final String TAG = "GeocoderProxy";
 
     private static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider";
 
-    private final ServiceWatcher mServiceWatcher;
-
-    public static GeocoderProxy createAndBind(Context context,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId) {
-        GeocoderProxy proxy = new GeocoderProxy(context, overlaySwitchResId,
-                defaultServicePackageNameResId, initialPackageNamesResId);
-        if (proxy.bind()) {
+    /**
+     * Creates and registers this proxy. If no suitable service is available for the proxy, returns
+     * null.
+     */
+    @Nullable
+    public static GeocoderProxy createAndRegister(Context context) {
+        GeocoderProxy proxy = new GeocoderProxy(context);
+        if (proxy.register()) {
             return proxy;
         } else {
             return null;
         }
     }
 
-    private GeocoderProxy(Context context,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId) {
-        mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
-                defaultServicePackageNameResId, initialPackageNamesResId,
-                BackgroundThread.getHandler());
+    private final ServiceWatcher mServiceWatcher;
+
+    private GeocoderProxy(Context context) {
+        mServiceWatcher = new ServiceWatcher(context, BackgroundThread.getHandler(), SERVICE_ACTION,
+                null, null,
+                com.android.internal.R.bool.config_enableGeocoderOverlay,
+                com.android.internal.R.string.config_geocoderProviderPackageName);
     }
 
-    private boolean bind() {
-        return mServiceWatcher.start();
-    }
-
-    public String getConnectedPackageName() {
-        return mServiceWatcher.getCurrentPackageName();
+    private boolean register() {
+        return mServiceWatcher.register();
     }
 
     public String getFromLocation(double latitude, double longitude, int maxResults,
@@ -83,5 +82,4 @@
                     maxResults, params, addrs);
         }, "Service not Available");
     }
-
 }
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index ce93661..f006fb1 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -22,7 +22,6 @@
 import android.content.ServiceConnection;
 import android.hardware.location.GeofenceHardwareService;
 import android.hardware.location.IGeofenceHardware;
-import android.location.IFusedGeofenceHardware;
 import android.location.IGeofenceProvider;
 import android.location.IGpsGeofenceHardware;
 import android.os.IBinder;
@@ -33,6 +32,8 @@
 import com.android.server.FgThread;
 import com.android.server.ServiceWatcher;
 
+import java.util.Objects;
+
 /**
  * @hide
  */
@@ -41,64 +42,41 @@
     private static final String TAG = "GeofenceProxy";
     private static final String SERVICE_ACTION = "com.android.location.service.GeofenceProvider";
 
-    private final Context mContext;
-    private final ServiceWatcher mServiceWatcher;
-
     @Nullable
-    private final IGpsGeofenceHardware mGpsGeofenceHardware;
-    @Nullable
-    private final IFusedGeofenceHardware mFusedGeofenceHardware;
-
-    private volatile IGeofenceHardware mGeofenceHardware;
-
-    private final ServiceWatcher.BinderRunner mUpdateGeofenceHardware = (binder) -> {
-        IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder);
-        try {
-            provider.setGeofenceHardware(mGeofenceHardware);
-        } catch (RemoteException e) {
-            Log.w(TAG, e);
-        }
-    };
-
-    public static GeofenceProxy createAndBind(Context context,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
-            @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
-        GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
-                defaultServicePackageNameResId, initialPackageNamesResId, gpsGeofence,
-                fusedGeofenceHardware);
-
-        if (proxy.bind()) {
+    public static GeofenceProxy createAndBind(Context context, IGpsGeofenceHardware gpsGeofence) {
+        GeofenceProxy proxy = new GeofenceProxy(context, gpsGeofence);
+        if (proxy.register(context)) {
             return proxy;
         } else {
             return null;
         }
     }
 
-    private GeofenceProxy(Context context,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
-            @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
-        mContext = context;
-        mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
-                defaultServicePackageNameResId, initialPackageNamesResId,
-                FgThread.getHandler()) {
-            @Override
-            protected void onBind() {
-                runOnBinder(mUpdateGeofenceHardware);
-            }
-        };
+    private final IGpsGeofenceHardware mGpsGeofenceHardware;
+    private final ServiceWatcher mServiceWatcher;
 
-        mGpsGeofenceHardware = gpsGeofence;
-        mFusedGeofenceHardware = fusedGeofenceHardware;
+    private volatile IGeofenceHardware mGeofenceHardware;
+
+    private GeofenceProxy(Context context, IGpsGeofenceHardware gpsGeofence) {
+        mGpsGeofenceHardware = Objects.requireNonNull(gpsGeofence);
+        mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), SERVICE_ACTION,
+                this::updateGeofenceHardware, null,
+                com.android.internal.R.bool.config_enableGeofenceOverlay,
+                com.android.internal.R.string.config_geofenceProviderPackageName);
 
         mGeofenceHardware = null;
     }
 
-    private boolean bind() {
-        if (mServiceWatcher.start()) {
-            mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
-                    new GeofenceProxyServiceConnection(), Context.BIND_AUTO_CREATE,
+    private void updateGeofenceHardware(IBinder binder) throws RemoteException {
+        IGeofenceProvider.Stub.asInterface(binder).setGeofenceHardware(mGeofenceHardware);
+    }
+
+    private boolean register(Context context) {
+        if (mServiceWatcher.register()) {
+            context.bindServiceAsUser(
+                    new Intent(context, GeofenceHardwareService.class),
+                    new GeofenceProxyServiceConnection(),
+                    Context.BIND_AUTO_CREATE,
                     UserHandle.SYSTEM);
             return true;
         }
@@ -113,24 +91,18 @@
             IGeofenceHardware geofenceHardware = IGeofenceHardware.Stub.asInterface(service);
 
             try {
-                if (mGpsGeofenceHardware != null) {
-                    geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
-                }
-                if (mFusedGeofenceHardware != null) {
-                    geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
-                }
-
+                geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
                 mGeofenceHardware = geofenceHardware;
-                mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
-            } catch (Exception e) {
-                Log.w(TAG, e);
+                mServiceWatcher.runOnBinder(GeofenceProxy.this::updateGeofenceHardware);
+            } catch (RemoteException e) {
+                Log.w(TAG, "unable to initialize geofence hardware", e);
             }
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
             mGeofenceHardware = null;
-            mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
+            mServiceWatcher.runOnBinder(GeofenceProxy.this::updateGeofenceHardware);
         }
     }
 }
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/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
new file mode 100644
index 0000000..9d9852b
--- /dev/null
+++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.location;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.location.ActivityRecognitionHardware;
+import android.hardware.location.IActivityRecognitionHardwareClient;
+import android.hardware.location.IActivityRecognitionHardwareWatcher;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.server.FgThread;
+import com.android.server.ServiceWatcher;
+
+/**
+ * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
+ *
+ * @hide
+ */
+public class HardwareActivityRecognitionProxy {
+
+    private static final String TAG = "ARProxy";
+    private static final String SERVICE_ACTION =
+            "com.android.location.service.ActivityRecognitionProvider";
+
+    /**
+     * Creates and registers this proxy. If no suitable service is available for the proxy, returns
+     * null.
+     */
+    @Nullable
+    public static HardwareActivityRecognitionProxy createAndRegister(Context context) {
+        HardwareActivityRecognitionProxy arProxy = new HardwareActivityRecognitionProxy(context);
+        if (arProxy.register()) {
+            return arProxy;
+        } else {
+            return null;
+        }
+    }
+
+    private final boolean mIsSupported;
+    private final ActivityRecognitionHardware mInstance;
+
+    private final ServiceWatcher mServiceWatcher;
+
+    private HardwareActivityRecognitionProxy(Context context) {
+        mIsSupported = ActivityRecognitionHardware.isSupported();
+        if (mIsSupported) {
+            mInstance = ActivityRecognitionHardware.getInstance(context);
+        } else {
+            mInstance = null;
+        }
+
+        mServiceWatcher = new ServiceWatcher(context,
+                FgThread.getHandler(),
+                SERVICE_ACTION,
+                this::onBind,
+                null,
+                com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
+                com.android.internal.R.string.config_activityRecognitionHardwarePackageName);
+    }
+
+    private boolean register() {
+        return mServiceWatcher.register();
+    }
+
+    private void onBind(IBinder binder) throws RemoteException {
+        String descriptor = binder.getInterfaceDescriptor();
+
+        if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) {
+            IActivityRecognitionHardwareWatcher watcher =
+                    IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
+            if (mInstance != null) {
+                watcher.onInstanceChanged(mInstance);
+            }
+        } else if (IActivityRecognitionHardwareClient.class.getCanonicalName().equals(descriptor)) {
+            IActivityRecognitionHardwareClient client =
+                    IActivityRecognitionHardwareClient.Stub.asInterface(binder);
+            client.onAvailabilityChanged(mIsSupported, mInstance);
+        } else {
+            Log.e(TAG, "Unknown descriptor: " + descriptor);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 8a149af..cf299fe 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -19,12 +19,11 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
 import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.location.Location;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.ArraySet;
@@ -35,7 +34,6 @@
 import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
 import com.android.server.FgThread;
-import com.android.server.LocationManagerService;
 import com.android.server.ServiceWatcher;
 
 import java.io.FileDescriptor;
@@ -49,17 +47,31 @@
 public class LocationProviderProxy extends AbstractLocationProvider {
 
     private static final String TAG = "LocationProviderProxy";
-    private static final boolean D = LocationManagerService.D;
 
     private static final int MAX_ADDITIONAL_PACKAGES = 2;
 
+    /**
+     * Creates and registers this proxy. If no suitable service is available for the proxy, returns
+     * null.
+     */
+    @Nullable
+    public static LocationProviderProxy createAndRegister(Context context, String action,
+            int enableOverlayResId, int nonOverlayPackageResId) {
+        LocationProviderProxy proxy = new LocationProviderProxy(context, action, enableOverlayResId,
+                nonOverlayPackageResId);
+        if (proxy.register()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
     private final ILocationProviderManager.Stub mManager = new ILocationProviderManager.Stub() {
         // executed on binder thread
         @Override
         public void onSetAdditionalProviderPackages(List<String> packageNames) {
-            int maxCount = Math.min(MAX_ADDITIONAL_PACKAGES, packageNames.size()) + 1;
+            int maxCount = Math.min(MAX_ADDITIONAL_PACKAGES, packageNames.size());
             ArraySet<String> allPackages = new ArraySet<>(maxCount);
-            allPackages.add(mServiceWatcher.getCurrentPackageName());
             for (String packageName : packageNames) {
                 if (packageNames.size() >= maxCount) {
                     return;
@@ -74,13 +86,19 @@
                 }
             }
 
+            // 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) {
+            setAllowed(allowed);
         }
 
         // executed on binder thread
@@ -100,63 +118,39 @@
 
     @Nullable private ProviderRequest mRequest;
 
-    /**
-     * Creates a new LocationProviderProxy and immediately begins binding to the best applicable
-     * service.
-     */
-    @Nullable
-    public static LocationProviderProxy createAndBind(Context context, String action,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId) {
-        LocationProviderProxy proxy = new LocationProviderProxy(context, FgThread.getHandler(),
-                action, overlaySwitchResId, defaultServicePackageNameResId,
-                initialPackageNamesResId);
-        if (proxy.bind()) {
-            return proxy;
-        } else {
-            return null;
-        }
-    }
+    private LocationProviderProxy(Context context, String action, int enableOverlayResId,
+            int nonOverlayPackageResId) {
+        super(context, FgThread.getExecutor());
 
-    private LocationProviderProxy(Context context, Handler handler, String action,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId) {
-        super(context, new HandlerExecutor(handler), Collections.emptySet());
-
-        mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId,
-                defaultServicePackageNameResId, initialPackageNamesResId, handler) {
-
-            @Override
-            protected void onBind() {
-                runOnBinder(LocationProviderProxy.this::initializeService);
-            }
-
-            @Override
-            protected void onUnbind() {
-                setState(State.EMPTY_STATE);
-            }
-        };
+        mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), action, this::onBind,
+                this::onUnbind, enableOverlayResId, nonOverlayPackageResId);
 
         mRequest = null;
     }
 
-    private boolean bind() {
-        return mServiceWatcher.start();
+    private boolean register() {
+        return mServiceWatcher.register();
     }
 
-    private void initializeService(IBinder binder) throws RemoteException {
-        ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-        if (D) Log.d(TAG, "applying state to connected service " + mServiceWatcher);
+    private void onBind(IBinder binder) throws RemoteException {
+        ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
 
-        setPackageNames(Collections.singleton(mServiceWatcher.getCurrentPackageName()));
+        ComponentName service = mServiceWatcher.getBoundService().component;
+        if (service != null) {
+            setPackageNames(Collections.singleton(service.getPackageName()));
+        }
 
-        service.setLocationProviderManager(mManager);
+        provider.setLocationProviderManager(mManager);
 
         if (mRequest != null) {
-            service.setRequest(mRequest, mRequest.workSource);
+            provider.setRequest(mRequest, mRequest.workSource);
         }
     }
 
+    private void onUnbind() {
+        setState(State.EMPTY_STATE);
+    }
+
     @Override
     public void onSetRequest(ProviderRequest request) {
         mServiceWatcher.runOnBinder(binder -> {
@@ -175,6 +169,14 @@
     }
 
     @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);
     }
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..18615f8 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);
         }
     }
     /**
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/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4a6fcdf7..a6ad57a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -103,6 +103,7 @@
 
     private static final int WAKELOCK_TIMEOUT = 5000;
     private static final int MEDIA_KEY_LISTENER_TIMEOUT = 1000;
+    private static final int SESSION_CREATION_LIMIT_PER_UID = 100;
 
     private final Context mContext;
     private final SessionManagerImpl mSessionManagerImpl;
@@ -428,6 +429,18 @@
             Log.d(TAG, "Destroying " + session);
         }
         FullUserRecord user = getFullUserRecordLocked(session.getUserId());
+
+        if (user != null) {
+            final int uid = session.getUid();
+            final int sessionCount = user.mUidToSessionCount.get(uid, 0);
+            if (sessionCount <= 0) {
+                Log.w(TAG, "destroySessionLocked: sessionCount should be positive. "
+                        + "sessionCount=" + sessionCount);
+            } else {
+                user.mUidToSessionCount.put(uid, sessionCount - 1);
+            }
+        }
+
         if (mGlobalPrioritySession == session) {
             mGlobalPrioritySession = null;
             if (session.isActive() && user != null) {
@@ -490,6 +503,20 @@
         }
     }
 
+    private boolean hasMediaControlPermission(int pid, int uid) {
+        // Check if it's system server or has MEDIA_CONTENT_CONTROL.
+        // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
+        // check here.
+        if (uid == Process.SYSTEM_UID || mContext.checkPermission(
+                android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        } else if (DEBUG) {
+            Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+        }
+        return false;
+    }
+
     /**
      * This checks if the component is an enabled notification listener for the
      * specified user. Enabled components may only operate on behalf of the user
@@ -544,6 +571,14 @@
                 throw new RuntimeException("Media Session owner died prematurely.", e);
             }
 
+            final int sessionCount = user.mUidToSessionCount.get(callerUid, 0);
+            if (sessionCount >= SESSION_CREATION_LIMIT_PER_UID
+                    && !hasMediaControlPermission(callerPid, callerUid)) {
+                throw new RuntimeException("Created too many sessions. count="
+                        + sessionCount + ")");
+            }
+            user.mUidToSessionCount.put(callerUid, sessionCount + 1);
+
             user.mPriorityStack.addSession(session);
             mHandler.postSessionsChanged(session);
 
@@ -723,6 +758,7 @@
                 mOnMediaKeyEventDispatchedListeners = new HashMap<>();
         private final HashMap<IBinder, OnMediaKeyEventSessionChangedListenerRecord>
                 mOnMediaKeyEventSessionChangedListeners = new HashMap<>();
+        private final SparseIntArray mUidToSessionCount = new SparseIntArray();
 
         private PendingIntent mLastMediaButtonReceiver;
         private ComponentName mRestoredMediaButtonReceiver;
@@ -1954,20 +1990,6 @@
             return resolvedUserId;
         }
 
-        private boolean hasMediaControlPermission(int pid, int uid) {
-            // Check if it's system server or has MEDIA_CONTENT_CONTROL.
-            // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
-            // check here.
-            if (uid == Process.SYSTEM_UID || mContext.checkPermission(
-                    android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
-                    == PackageManager.PERMISSION_GRANTED) {
-                return true;
-            } else if (DEBUG) {
-                Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
-            }
-            return false;
-        }
-
         private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName)
                 throws RemoteException {
             // You may not access another user's content as an enabled listener.
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6f43952..e92f3ec 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -251,8 +251,8 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.UiThread;
-import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
 import com.android.server.notification.ManagedServices.UserProfiles;
 import com.android.server.pm.PackageManagerService;
@@ -413,8 +413,8 @@
     private final HandlerThread mRankingThread = new HandlerThread("ranker",
             Process.THREAD_PRIORITY_BACKGROUND);
 
-    private Light mNotificationLight;
-    Light mAttentionLight;
+    private LogicalLight mNotificationLight;
+    LogicalLight mAttentionLight;
 
     private long[] mFallbackVibrationPattern;
     private boolean mUseAttentionLight;
@@ -513,6 +513,7 @@
     private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
 
     private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
+    private NotificationRecordLogger mNotificationRecordLogger;
 
     private static class Archive {
         final int mBufferSize;
@@ -1727,7 +1728,14 @@
     }
 
     public NotificationManagerService(Context context) {
+        this(context, new NotificationRecordLoggerImpl());
+    }
+
+    @VisibleForTesting
+    public NotificationManagerService(Context context,
+            NotificationRecordLogger notificationRecordLogger) {
         super(context);
+        mNotificationRecordLogger = notificationRecordLogger;
         Notification.processWhitelistToken = WHITELIST_TOKEN;
     }
 
@@ -1753,7 +1761,7 @@
     }
 
     @VisibleForTesting
-    void setLights(Light light) {
+    void setLights(LogicalLight light) {
         mNotificationLight = light;
         mAttentionLight = light;
         mNotificationPulseEnabled = true;
@@ -6304,9 +6312,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 +6356,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 +6588,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 +6692,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 +6715,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")
@@ -7875,7 +7895,7 @@
             NotificationRecord.Light light = ledNotification.getLight();
             if (light != null && mNotificationPulseEnabled) {
                 // pulse repeatedly
-                mNotificationLight.setFlashing(light.color, Light.LIGHT_FLASH_TIMED,
+                mNotificationLight.setFlashing(light.color, LogicalLight.LIGHT_FLASH_TIMED,
                         light.onMs, light.offMs);
             }
         }
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/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index ac3bf9a..0a9f923 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;
 
     /**
@@ -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/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 78e1719..6e7e5d8 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -302,8 +302,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);
         }
     }
 
@@ -511,6 +512,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 +662,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 ed955a2..a223326 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;
@@ -203,8 +205,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 +307,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;
         }
     }
 
@@ -363,7 +372,9 @@
     // 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 +386,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) {
@@ -597,6 +618,7 @@
             info.isStagedSessionReady = mStagedSessionReady;
             info.isStagedSessionFailed = mStagedSessionFailed;
             info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
+            info.createdMillis = createdMillis;
             info.updatedMillis = updatedMillis;
         }
         return info;
@@ -703,7 +725,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);
     }
@@ -714,9 +740,9 @@
     }
 
     @GuardedBy("mLock")
-    private File[] getAddedFilesLocked() {
+    private File[] getAddedApksLocked() {
         String[] names = getNamesLocked();
-        return filterFiles(stageDir, names, sAddedFilter);
+        return filterFiles(stageDir, names, sAddedApkFilter);
     }
 
     @GuardedBy("mLock")
@@ -1329,7 +1355,7 @@
 
                 prepareDataLoader();
 
-                if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+                if (isApexInstallation()) {
                     validateApexInstallLocked();
                 } else {
                     validateApkInstallLocked(pkgInfo);
@@ -1360,15 +1386,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;
@@ -1377,9 +1403,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);
             }
@@ -1455,7 +1485,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);
@@ -1539,7 +1569,7 @@
         }
 
         final IPackageInstallObserver2 localObserver;
-        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+        if (isApexInstallation()) {
             localObserver = null;
         } else {
             if (!params.isMultiPackage) {
@@ -1674,6 +1704,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
@@ -1682,7 +1719,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");
         }
@@ -1770,7 +1807,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");
         }
@@ -2325,11 +2362,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);
@@ -2338,12 +2387,12 @@
         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.");
@@ -2356,7 +2405,7 @@
             assertCallerIsOwnerOrRootLocked();
             assertPreparedAndNotSealedLocked("removeFile");
 
-            mFiles.add(FileInfo.removed(getRemoveMarkerName(name)));
+            mFiles.add(FileInfo.removed(location, getRemoveMarkerName(name)));
         }
     }
 
@@ -2891,9 +2940,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);
             }
         }
@@ -3024,9 +3075,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 3a33313..6c8e7b0 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;
@@ -185,6 +186,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
+import android.content.pm.ProcessInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.SELinuxUtil;
@@ -385,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;
@@ -2722,7 +2725,7 @@
         t.traceBegin("get system config");
         SystemConfig systemConfig = SystemConfig.getInstance();
         mAvailableFeatures = systemConfig.getAvailableFeatures();
-        ApplicationPackageManager.invalidateSysFeatureCache();
+        ApplicationPackageManager.invalidateHasSystemFeatureCache();
         t.traceEnd();
 
         mProtectedPackages = new ProtectedPackages(mContext);
@@ -2866,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");
@@ -2891,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);
             }
 
 
@@ -2998,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.
@@ -3158,6 +3184,7 @@
                 // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
                 // SELinux domain.
                 setting.fixSeInfoLocked();
+                setting.updateProcesses();
             }
 
             // Now that we know all the packages we are keeping,
@@ -4552,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);
@@ -8572,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);
@@ -8592,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);
             }
         }
     }
@@ -14373,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.
@@ -17697,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.
@@ -20209,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();
 
@@ -23096,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
@@ -23487,6 +23526,20 @@
         }
 
         @Override
+        public ArrayMap<String, ProcessInfo> getProcessesForUid(int uid) {
+            synchronized (mLock) {
+                return getProcessesForUidLocked(uid);
+            }
+        }
+
+        @Override
+        public int[] getPermissionGids(String permissionName, int userId) {
+            synchronized (mLock) {
+                return getPermissionGidsLocked(permissionName, userId);
+            }
+        }
+
+        @Override
         public boolean isOnlyCoreApps() {
             return PackageManagerService.this.isOnlyCoreApps();
         }
@@ -23741,6 +23794,30 @@
         return res != null ? res : EmptyArray.STRING;
     }
 
+    @GuardedBy("mLock")
+    public ArrayMap<String, ProcessInfo> getProcessesForUidLocked(int uid) {
+        final int appId = UserHandle.getAppId(uid);
+        final SettingBase obj = mSettings.getSettingLPr(appId);
+        if (obj instanceof SharedUserSetting) {
+            final SharedUserSetting sus = (SharedUserSetting) obj;
+            return PackageInfoUtils.generateProcessInfo(sus.processes, 0);
+        } else if (obj instanceof PackageSetting) {
+            final PackageSetting ps = (PackageSetting) obj;
+            return PackageInfoUtils.generateProcessInfo(ps.pkg.getProcesses(), 0);
+        }
+        return null;
+    }
+
+    @GuardedBy("mLock")
+    public int[] getPermissionGidsLocked(String permissionName, int userId) {
+        BasePermission perm
+                = mPermissionManager.getPermissionSettings().getPermission(permissionName);
+        if (perm != null) {
+            return perm.computeGids(userId);
+        }
+        return null;
+    }
+
     @Override
     public int getRuntimePermissionsVersion(@UserIdInt int userId) {
         Preconditions.checkArgumentNonnegative(userId);
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..281c44a 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;
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/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 0a42ccf..b9bb9e0 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -19,7 +19,9 @@
 import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.ComponentParseUtils;
 import android.service.pm.PackageServiceDumpProto;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
@@ -51,6 +53,8 @@
     final PackageSignatures signatures = new PackageSignatures();
     Boolean signaturesChanged;
 
+    ArrayMap<String, ComponentParseUtils.ParsedProcess> processes;
+
     SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
         super(_pkgFlags, _pkgPrivateFlags);
         uidFlags =  _pkgFlags;
@@ -72,6 +76,25 @@
         proto.end(token);
     }
 
+    void addProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> newProcs) {
+        if (newProcs != null) {
+            final int numProcs = newProcs.size();
+            if (processes == null) {
+                processes = new ArrayMap<>(numProcs);
+            }
+            for (int i = 0; i < numProcs; i++) {
+                ComponentParseUtils.ParsedProcess newProc = newProcs.valueAt(i);
+                ComponentParseUtils.ParsedProcess proc = processes.get(newProc.name);
+                if (proc == null) {
+                    proc = new ComponentParseUtils.ParsedProcess(newProc);
+                    processes.put(newProc.name, proc);
+                } else {
+                    proc.addStateFrom(newProc);
+                }
+            }
+        }
+    }
+
     boolean removePackage(PackageSetting packageSetting) {
         if (!packages.remove(packageSetting)) {
             return false;
@@ -91,6 +114,8 @@
             }
             setPrivateFlags(aggregatedPrivateFlags);
         }
+        // recalculate processes.
+        updateProcesses();
         return true;
     }
 
@@ -104,6 +129,9 @@
             setFlags(this.pkgFlags | packageSetting.pkgFlags);
             setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
         }
+        if (packageSetting.pkg != null) {
+            addProcesses(packageSetting.pkg.getProcesses());
+        }
     }
 
     public @Nullable List<AndroidPackage> getPackages() {
@@ -148,6 +176,16 @@
         }
     }
 
+    /**
+     * Update tracked data about processes based on all known packages in the shared user ID.
+     */
+    public void updateProcesses() {
+        processes = null;
+        for (int i = packages.size() - 1; i >= 0; i--) {
+            addProcesses(packages.valueAt(i).pkg.getProcesses());
+        }
+    }
+
     /** Returns userIds which doesn't have any packages with this sharedUserId */
     public int[] getNotInstalledUserIds() {
         int[] excludedUserIds = null;
@@ -176,6 +214,17 @@
         this.packages.clear();
         this.packages.addAll(sharedUser.packages);
         this.signaturesChanged = sharedUser.signaturesChanged;
+        if (sharedUser.processes != null) {
+            final int numProcs = sharedUser.processes.size();
+            this.processes = new ArrayMap<>(numProcs);
+            for (int i = 0; i < numProcs; i++) {
+                ComponentParseUtils.ParsedProcess proc =
+                        new ComponentParseUtils.ParsedProcess(sharedUser.processes.valueAt(i));
+                this.processes.put(proc.name, proc);
+            }
+        } else {
+            this.processes = null;
+        }
         return this;
     }
 }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ec9049e..c3e7f62 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4876,7 +4876,7 @@
                     mBootMsgDialog.getWindow().setDimAmount(1);
                     WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
                     lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-                    lp.setFitWindowInsetsTypes(0 /* types */);
+                    lp.setFitInsetsTypes(0 /* types */);
                     mBootMsgDialog.getWindow().setAttributes(lp);
                     mBootMsgDialog.setCancelable(false);
                     mBootMsgDialog.show();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ca36869..3f3a133 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -16,8 +16,8 @@
 
 package com.android.server.power;
 
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -96,8 +96,8 @@
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
-import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.power.batterysaver.BatterySaverController;
 import com.android.server.power.batterysaver.BatterySaverPolicy;
@@ -257,7 +257,7 @@
     private WirelessChargerDetector mWirelessChargerDetector;
     private SettingsObserver mSettingsObserver;
     private DreamManagerInternal mDreamManager;
-    private Light mAttentionLight;
+    private LogicalLight mAttentionLight;
 
     private InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
 
@@ -3347,7 +3347,7 @@
     }
 
     private void setAttentionLightInternal(boolean on, int color) {
-        Light light;
+        LogicalLight light;
         synchronized (mLock) {
             if (!mSystemReady) {
                 return;
@@ -3356,7 +3356,7 @@
         }
 
         // Control light outside of lock.
-        light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
+        light.setFlashing(color, LogicalLight.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
     }
 
     private void setDozeAfterScreenOffInternal(boolean on) {
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/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index a0e6be4..39d1a51 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;
@@ -32,11 +31,8 @@
 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;
@@ -134,7 +118,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;
@@ -156,20 +139,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;
@@ -229,6 +207,25 @@
         mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
 
+        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");
+            }
+        }
+
         // Initialize state for CPU_TIME_PER_FREQ atom
         PowerProfile powerProfile = new PowerProfile(mContext);
         final int numClusters = powerProfile.getNumCpuClusters();
@@ -2896,4 +2893,29 @@
                 BackgroundThread.getExecutor()
         );
     }
+
+
+    // 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/utils/FlagNamespaceUtils.java b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
deleted file mode 100644
index f8c7447..0000000
--- a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
+++ /dev/null
@@ -1,151 +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.annotation.Nullable;
-import android.provider.DeviceConfig;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.RescueParty;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Utilities for interacting with the {@link android.provider.DeviceConfig}.
- *
- * @hide
- */
-public final class FlagNamespaceUtils {
-    /**
-     * Special String used for communicating through {@link #RESET_PLATFORM_PACKAGE_FLAG} that
-     * Settings were reset by the RescueParty, no actual namespace with this name exists in
-     * {@link DeviceConfig}.
-     */
-    public static final String NAMESPACE_NO_PACKAGE = "no_package";
-
-    /**
-     * Name of the special namespace in DeviceConfig table used for communicating resets.
-     */
-    @VisibleForTesting
-    public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
-    /**
-     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link
-     * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the
-     * first time flags are written to the new namespace in the {@link DeviceConfig}.
-     */
-    @VisibleForTesting
-    public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
-    /**
-     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter
-     * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently
-     * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given
-     * namespace flags are reset.
-     */
-    @VisibleForTesting
-    public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
-    private static final String DELIMITER = ":";
-    /**
-     * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG}
-     * when communicating recently reset by the RescueParty namespace values.
-     */
-    private static final int MAX_COUNTER_VALUE = 50;
-
-    private static int sKnownResetNamespacesFlagCounter = -1;
-
-    /**
-     * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with
-     * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for each namespace
-     * in the consumed namespacesList. These flags are used for communicating the namespaces
-     * (aka platform packages) whose flags in {@link DeviceConfig} were just reset
-     * by the RescueParty.
-     */
-    public static void addToKnownResetNamespaces(@Nullable List<String> namespacesList) {
-        if (namespacesList == null) {
-            return;
-        }
-        for (String namespace : namespacesList) {
-            addToKnownResetNamespaces(namespace);
-        }
-    }
-
-    /**
-     * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with
-     * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for the consumed namespace.
-     * This flag is used for communicating the namespace (aka platform package) whose flags
-     * in {@link DeviceConfig} were just reset by the RescueParty.
-     */
-    public static void addToKnownResetNamespaces(String namespace) {
-        int nextFlagCounter = incrementAndRetrieveResetNamespacesFlagCounter();
-        DeviceConfig.setProperty(NAMESPACE_RESCUE_PARTY,
-                RESET_PLATFORM_PACKAGE_FLAG + nextFlagCounter,
-                namespace, /*makeDefault=*/ true);
-    }
-
-    /**
-     * Reset all namespaces in DeviceConfig with consumed resetMode.
-     */
-    public static void resetDeviceConfig(int resetMode) {
-        resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList());
-    }
-
-    /**
-     * Reset all consumed namespaces in DeviceConfig with consumed resetMode.
-     */
-    public static void resetDeviceConfig(int resetMode, List<String> namespacesList) {
-        for (String namespace : namespacesList) {
-            DeviceConfig.resetToDefaults(resetMode, namespace);
-        }
-        addToKnownResetNamespaces(namespacesList);
-    }
-
-    /**
-     * Resets known reset namespaces flag counter for tests only.
-     */
-    @VisibleForTesting
-    public static void resetKnownResetNamespacesFlagCounterForTest() {
-        sKnownResetNamespacesFlagCounter = -1;
-    }
-
-    /**
-     * Returns a list of all known DeviceConfig namespaces, except for the special {@link
-     * #NAMESPACE_RESCUE_PARTY}
-     */
-    private static List<String> getAllKnownDeviceConfigNamespacesList() {
-        String namespacesStr = DeviceConfig.getProperty(NAMESPACE_RESCUE_PARTY,
-                ALL_KNOWN_NAMESPACES_FLAG);
-        List<String> namespacesList = toStringList(namespacesStr);
-        namespacesList.remove(NAMESPACE_RESCUE_PARTY);
-        return namespacesList;
-    }
-
-    private static List<String> toStringList(String serialized) {
-        if (serialized == null || serialized.length() == 0) {
-            return new ArrayList<>();
-        }
-        return Arrays.asList(serialized.split(DELIMITER));
-    }
-
-    private static int incrementAndRetrieveResetNamespacesFlagCounter() {
-        sKnownResetNamespacesFlagCounter++;
-        if (sKnownResetNamespacesFlagCounter == MAX_COUNTER_VALUE) {
-            sKnownResetNamespacesFlagCounter = 0;
-        }
-        return sKnownResetNamespacesFlagCounter;
-    }
-}
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..33e18c1 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;
@@ -495,7 +494,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 +612,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 +895,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 +1627,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 +1640,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 +2654,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 +3356,7 @@
         }
         mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
         mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
+        mLastContainsTurnScreenOnWindow = containsTurnScreenOnWindow();
     }
 
     boolean containsDismissKeyguardWindow() {
@@ -4362,6 +4355,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 +4453,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 +4504,7 @@
                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
             }
             setVisibility(true);
-            sleeping = false;
+            mSetToSleep = false;
             app.postPendingUiCleanMsg(true);
             if (reportToClient) {
                 mClientVisibilityDeferred = false;
@@ -4506,7 +4514,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 +5459,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 +7403,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;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 942be84..663423f 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1263,6 +1263,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 +1314,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 +1324,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) {
@@ -2040,8 +2037,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 +2088,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 +2357,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 +3990,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 +4043,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/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..36bee87 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3116,6 +3116,8 @@
             }
         }
 
+        onWindowFocusChanged(oldFocus, newFocus);
+
         int focusChanged = getDisplayPolicy().focusChangedLw(oldFocus, newFocus);
 
         if (imWindowChanged && oldFocus != mInputMethodWindow) {
@@ -3158,6 +3160,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.
      *
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4f1d40e..f8df883 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -63,7 +63,6 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -362,7 +361,6 @@
     private static final Rect sTmpRect = new Rect();
     private static final Rect sTmpNavFrame = new Rect();
     private static final Rect sTmpLastParentFrame = new Rect();
-    private static final int[] sTmpTypesAndSides = new int[2];
 
     private WindowState mTopFullscreenOpaqueWindowState;
     private WindowState mTopFullscreenOpaqueOrDimmingWindowState;
@@ -888,6 +886,21 @@
                 // Toasts can't be clickable
                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                 break;
+
+            case TYPE_BASE_APPLICATION:
+
+                // A non-translucent main app window isn't allowed to fit insets, as it would create
+                // a hole on the display!
+                if (attrs.isFullscreen() && win.mActivityRecord != null
+                        && win.mActivityRecord.fillsParent()
+                        && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
+                        && attrs.getFitInsetsTypes() != 0) {
+                    throw new RuntimeException("Illegal attributes: Main activity window that isn't"
+                            + " translucent trying to fit insets: "
+                            + attrs.getFitInsetsTypes()
+                            + " attrs=" + attrs);
+                }
+                break;
         }
     }
 
@@ -1247,7 +1260,7 @@
 
         if (layoutInScreenAndInsetDecor && !screenDecor) {
             if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
-                    || (attrs.getFitWindowInsetsTypes() & Type.navigationBars()) == 0) {
+                    || (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) {
                 outFrame.set(displayFrames.mUnrestricted);
             } else {
                 outFrame.set(displayFrames.mRestricted);
@@ -1300,21 +1313,6 @@
         }
     }
 
-    private static void getImpliedTypesAndSidesToFit(LayoutParams attrs, int[] typesAndSides) {
-        typesAndSides[0] = attrs.getFitWindowInsetsTypes();
-        typesAndSides[1] = attrs.getFitWindowInsetsSides();
-        final boolean forceDrawsBarBackgrounds =
-                (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
-                        && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
-        if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 || forceDrawsBarBackgrounds) {
-            if ((attrs.privateFlags & PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND) != 0) {
-                typesAndSides[1] &= ~Side.BOTTOM;
-            } else {
-                typesAndSides[0] &= ~Type.systemBars();
-            }
-        }
-    }
-
     // TODO(b/118118435): remove after migration
     private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
         int impliedFlags = 0;
@@ -1878,16 +1876,15 @@
         sf.set(displayFrames.mStable);
 
         if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
-            getImpliedTypesAndSidesToFit(attrs, sTmpTypesAndSides);
-            final @InsetsType int typesToFit = sTmpTypesAndSides[0];
-            final @InsetsSide int sidesToFit = sTmpTypesAndSides[1];
+            final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
+            final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
             final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
             final Rect dfu = displayFrames.mUnrestricted;
             Insets insets = Insets.of(0, 0, 0, 0);
             for (int i = types.size() - 1; i >= 0; i--) {
                 insets = Insets.max(insets, mDisplayContent.getInsetsPolicy()
                         .getInsetsForDispatch(win).getSource(types.valueAt(i))
-                        .calculateInsets(dfu, attrs.getFitIgnoreVisibility()));
+                        .calculateInsets(dfu, attrs.isFitInsetsIgnoringVisibility()));
             }
             final int left = (sidesToFit & Side.LEFT) != 0 ? insets.left : 0;
             final int top = (sidesToFit & Side.TOP) != 0 ? insets.top : 0;
diff --git a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
index bef1442..ef6f847 100644
--- a/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/wm/ImmersiveModeConfirmation.java
@@ -190,7 +190,7 @@
                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                 PixelFormat.TRANSLUCENT);
-        lp.setFitWindowInsetsTypes(lp.getFitWindowInsetsTypes() & ~Type.statusBars());
+        lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~Type.statusBars());
         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("ImmersiveModeConfirmation");
         lp.windowAnimations = com.android.internal.R.style.Animation_ImmersiveModeConfirmation;
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/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/Task.java b/services/core/java/com/android/server/wm/Task.java
index 917b437..19461c5 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;
@@ -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}.
@@ -496,7 +501,7 @@
     }
 
     class TaskToken extends RemoteToken {
-        TaskToken(ConfigurationContainer container) {
+        TaskToken(WindowContainer container) {
             super(container);
         }
 
@@ -1869,6 +1874,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 +2533,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 +2748,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 +3151,9 @@
         } else {
             mTmpDimBoundsRect.offsetTo(0, 0);
         }
+
+        updateSurfaceCrop();
+
         if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
             scheduleAnimation();
         }
@@ -3925,4 +3953,58 @@
             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/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1c876d9..0ab5f91 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;
@@ -2259,4 +2270,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 81a4c68..1360711 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;
@@ -71,6 +72,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
+import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
@@ -121,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;
@@ -419,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.
@@ -720,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());
@@ -742,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
@@ -780,6 +792,11 @@
                 return;
             }
 
+            if (mRenderShadowsInCompositorUri.equals(uri)) {
+                setShadowRenderer();
+                return;
+            }
+
             @UpdateAnimationScaleMode
             final int mode;
             if (mWindowAnimationScaleUri.equals(uri)) {
@@ -861,6 +878,11 @@
         }
     }
 
+    private void setShadowRenderer() {
+        mRenderShadowsInCompositor = Settings.Global.getInt(mContext.getContentResolver(),
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0;
+    }
+
     PowerManager mPowerManager;
     PowerManagerInternal mPowerManagerInternal;
 
@@ -1247,6 +1269,7 @@
         float[] spotColor = {0.f, 0.f, 0.f, spotShadowAlpha};
         SurfaceControl.setGlobalShadowSettings(ambientColor, spotColor, lightY, lightZ,
                 lightRadius);
+        setShadowRenderer();
     }
 
     /**
@@ -1367,52 +1390,10 @@
             boolean addToastWindowRequiresToken = false;
 
             if (token == null) {
-                if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
-                    ProtoLog.w(WM_ERROR, "Attempted to add application window with unknown token "
-                            + "%s.  Aborting.", attrs.token);
+                if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
+                        rootType, attrs.token, attrs.packageName)) {
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
-                if (rootType == TYPE_INPUT_METHOD) {
-                    ProtoLog.w(WM_ERROR, "Attempted to add input method window with unknown token "
-                            + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (rootType == TYPE_VOICE_INTERACTION) {
-                    ProtoLog.w(WM_ERROR,
-                            "Attempted to add voice interaction window with unknown token "
-                                    + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (rootType == TYPE_WALLPAPER) {
-                    ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with unknown token "
-                            + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (rootType == TYPE_DREAM) {
-                    ProtoLog.w(WM_ERROR, "Attempted to add Dream window with unknown token "
-                            + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (rootType == TYPE_QS_DIALOG) {
-                    ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
-                            + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
-                    ProtoLog.w(WM_ERROR,
-                            "Attempted to add Accessibility overlay window with unknown token "
-                                    + "%s.  Aborting.", attrs.token);
-                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                }
-                if (type == TYPE_TOAST) {
-                    // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
-                    if (doesAddToastWindowRequireToken(attrs.packageName, callingUid,
-                            parentWindow)) {
-                        ProtoLog.w(WM_ERROR, "Attempted to add a toast window with unknown token "
-                                + "%s.  Aborting.", attrs.token);
-                        return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-                    }
-                }
                 final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                 final boolean isRoundedCornerOverlay =
                         (attrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
@@ -1697,6 +1678,56 @@
         return res;
     }
 
+    private boolean unprivilegedAppCanCreateTokenWith(WindowState parentWindow,
+            int callingUid, int type, int rootType, IBinder tokenForLog, String packageName) {
+        if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
+            ProtoLog.w(WM_ERROR, "Attempted to add application window with unknown token "
+                    + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_INPUT_METHOD) {
+            ProtoLog.w(WM_ERROR, "Attempted to add input method window with unknown token "
+                    + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_VOICE_INTERACTION) {
+            ProtoLog.w(WM_ERROR,
+                    "Attempted to add voice interaction window with unknown token "
+                            + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_WALLPAPER) {
+            ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with unknown token "
+                    + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_DREAM) {
+            ProtoLog.w(WM_ERROR, "Attempted to add Dream window with unknown token "
+                    + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_QS_DIALOG) {
+            ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with unknown token "
+                    + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
+            ProtoLog.w(WM_ERROR,
+                    "Attempted to add Accessibility overlay window with unknown token "
+                            + "%s.  Aborting.", tokenForLog);
+            return false;
+        }
+        if (type == TYPE_TOAST) {
+            // Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
+            if (doesAddToastWindowRequireToken(packageName, callingUid, parentWindow)) {
+                ProtoLog.w(WM_ERROR, "Attempted to add a toast window with unknown token "
+                        + "%s.  Aborting.", tokenForLog);
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Get existing {@link DisplayContent} or create a new one if the display is registered in
      * DisplayManager.
@@ -2501,16 +2532,36 @@
 
     @Override
     public void addWindowToken(IBinder binder, int type, int displayId) {
-        if (!checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()")) {
-            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+        addWindowContextToken(binder, type, displayId, null);
+    }
+
+    @Override
+    public int addWindowContextToken(IBinder binder, int type, int displayId, String packageName) {
+        final boolean callerCanManageAppTokens =
+                checkCallingPermission(MANAGE_APP_TOKENS, "addWindowToken()");
+        if (!callerCanManageAppTokens) {
+            // TODO(window-context): refactor checkAddPermission to not take attrs.
+            LayoutParams attrs = new LayoutParams(type);
+            attrs.packageName = packageName;
+            final int res = mPolicy.checkAddPermission(attrs, new int[1]);
+            if (res != ADD_OKAY) {
+                return res;
+            }
         }
 
         synchronized (mGlobalLock) {
+            if (!callerCanManageAppTokens) {
+                if (!unprivilegedAppCanCreateTokenWith(null, Binder.getCallingUid(), type, type,
+                        null, packageName) || packageName == null) {
+                    throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+                }
+            }
+
             final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
             if (dc == null) {
                 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add token: %s"
                         + " for non-exiting displayId=%d", binder, displayId);
-                return;
+                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
             }
 
             WindowToken token = dc.getWindowToken(binder);
@@ -2518,15 +2569,28 @@
                 ProtoLog.w(WM_ERROR, "addWindowToken: Attempted to add binder token: %s"
                         + " for already created window token: %s"
                         + " displayId=%d", binder, token, displayId);
-                return;
+                return WindowManagerGlobal.ADD_DUPLICATE_ADD;
             }
+            // TODO(window-container): Clean up dead tokens
             if (type == TYPE_WALLPAPER) {
-                new WallpaperWindowToken(this, binder, true, dc,
-                        true /* ownerCanManageAppTokens */);
+                new WallpaperWindowToken(this, binder, true, dc, callerCanManageAppTokens);
             } else {
-                new WindowToken(this, binder, type, true, dc, true /* ownerCanManageAppTokens */);
+                new WindowToken(this, binder, type, true, dc, callerCanManageAppTokens);
             }
         }
+        return WindowManagerGlobal.ADD_OKAY;
+    }
+
+    @Override
+    public boolean isWindowToken(IBinder binder) {
+        synchronized (mGlobalLock) {
+            final WindowToken windowToken = mRoot.getWindowToken(binder);
+            if (windowToken == null) {
+                return false;
+            }
+            // We don't allow activity tokens in WindowContext. TODO(window-context): rename method
+            return windowToken.asActivityRecord() == null;
+        }
     }
 
     @Override
@@ -2954,7 +3018,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();
     }
 
@@ -7885,4 +7955,33 @@
         return mDisplayWindowSettings.shouldShowImeLocked(displayContent)
                 || mForceDesktopModeOnExternalDisplays;
     }
+
+    @Override
+    public void getWindowInsets(WindowManager.LayoutParams attrs,
+            int displayId, Rect outContentInsets, Rect outStableInsets,
+            DisplayCutout.ParcelableWrapper displayCutout) {
+        synchronized (mGlobalLock) {
+            final DisplayContent dc = mRoot.getDisplayContent(displayId);
+            final WindowToken windowToken = dc.getWindowToken(attrs.token);
+            final ActivityRecord activity;
+            if (windowToken != null && windowToken.asActivityRecord() != null) {
+                activity = windowToken.asActivityRecord();
+            } else {
+                activity = null;
+            }
+            final Rect taskBounds = new Rect();
+            final boolean floatingStack;
+            if (activity != null && activity.getTask() != null) {
+                final Task task = activity.getTask();
+                task.getBounds(taskBounds);
+                floatingStack = task.isFloating();
+            } else {
+                floatingStack = false;
+            }
+            final DisplayFrames displayFrames = dc.mDisplayFrames;
+            final DisplayPolicy policy = dc.getDisplayPolicy();
+            policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
+                    new Rect(), outContentInsets, outStableInsets, displayCutout);
+        }
+    }
 }
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 8641059..9b85a7b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -68,4 +68,18 @@
     public boolean isOrganizationOwnedDeviceWithManagedProfile() {
         return false;
     }
+
+    public int getPersonalAppsSuspendedReasons(ComponentName admin) {
+        return 0;
+    }
+
+    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 7830c60..d7ea2f5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.BIND_DEVICE_ADMIN;
 import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
 import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
+import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
@@ -66,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;
@@ -126,6 +130,7 @@
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.DevicePolicyManager.PasswordComplexity;
+import android.app.admin.DevicePolicyManager.PersonalAppSuspensionReason;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.DeviceStateCache;
 import android.app.admin.FactoryResetProtectionPolicy;
@@ -175,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;
@@ -254,6 +260,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.telephony.SmsApplication;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
@@ -312,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.
@@ -375,14 +381,21 @@
 
     private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
 
+    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";
@@ -445,6 +458,8 @@
     // A collection of user restrictions that are deprecated and should simply be ignored.
     private static final Set<String> DEPRECATED_USER_RESTRICTIONS;
     private static final String AB_DEVICE_KEY = "ro.build.ab_update";
+    // Permissions related to location which must not be granted automatically
+    private static  final Set<String> LOCATION_PERMISSIONS;
 
     static {
         SECURE_SETTINGS_WHITELIST = new ArraySet<>();
@@ -489,6 +504,11 @@
         DEPRECATED_USER_RESTRICTIONS = Sets.newHashSet(
                 UserManager.DISALLOW_ADD_MANAGED_PROFILE,
                 UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
+
+        LOCATION_PERMISSIONS = Sets.newHashSet(
+                permission.ACCESS_FINE_LOCATION,
+                permission.ACCESS_BACKGROUND_LOCATION,
+                permission.ACCESS_COARSE_LOCATION);
     }
 
     /**
@@ -787,6 +807,10 @@
 
         long mPasswordTokenHandle = 0;
 
+        // 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;
         }
@@ -832,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)) {
@@ -879,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)
@@ -902,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) {
@@ -1016,6 +1055,9 @@
         private static final String TAG_CROSS_PROFILE_PACKAGES = "cross-profile-packages";
         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;
 
@@ -1138,6 +1180,14 @@
         // represented as an empty list.
         List<String> mCrossProfilePackages = Collections.emptyList();
 
+        // 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;
             isParent = parent;
@@ -1347,8 +1397,7 @@
                 writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
             }
             if (isLogoutEnabled) {
-                writeAttributeValueToXml(
-                        out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
+                writeAttributeValueToXml(out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
             }
             if (startUserSessionMessage != null) {
                 writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
@@ -1369,6 +1418,15 @@
                 mFactoryResetProtectionPolicy.writeToXml(out);
                 out.endTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
             }
+            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 {
@@ -1605,6 +1663,15 @@
                 } else if (TAG_FACTORY_RESET_PROTECTION_POLICY.equals(tag)) {
                     mFactoryResetProtectionPolicy = FactoryResetProtectionPolicy.readFromXml(
                                 parser);
+                } 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);
@@ -1830,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);
         }
     }
 
@@ -2024,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));
@@ -2348,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();
@@ -3411,6 +3490,12 @@
                 out.endTag(null, TAG_PROTECTED_PACKAGES);
             }
 
+            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");
 
             out.endDocument();
@@ -3627,6 +3712,9 @@
                     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_APPS_SUSPENDED.equals(tag)) {
+                    policy.mAppsSuspended =
+                            Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -3767,6 +3855,10 @@
                 synchronized (getLockObject()) {
                     maybeMigrateToProfileOnOrganizationOwnedDeviceLocked();
                 }
+                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.
@@ -9361,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();
         }
     }
@@ -9749,7 +9839,7 @@
                 }
                 AccessibilityManager accessibilityManager = getAccessibilityManagerForUser(userId);
                 enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(
-                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+                        FEEDBACK_ALL_MASK);
             } finally {
                 mInjector.binderRestoreCallingIdentity(id);
             }
@@ -10671,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;
@@ -10702,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");
         }
     }
 
@@ -11447,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);
@@ -12124,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 {
@@ -12133,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)
@@ -12390,6 +12513,14 @@
                             true);
                 }
 
+                // Prevent granting location-related permissions without user consent.
+                if (LOCATION_PERMISSIONS.contains(permission)
+                        && grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
+                        && !isUnattendedManagedKioskUnchecked()) {
+                    callback.sendResult(null);
+                    return;
+                }
+
                 if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
                         || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
                         || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
@@ -14789,7 +14920,7 @@
                 .setAdmin(admin)
                 .setBoolean(isDeviceAB())
                 .write();
-        enforceDeviceOwner(admin);
+        enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
         mInjector.binderWithCleanCallingIdentity(() -> {
             UpdateInstaller updateInstaller;
             if (isDeviceAB()) {
@@ -14981,21 +15112,22 @@
         }
     }
 
+    private boolean isUnattendedManagedKioskUnchecked() {
+        try {
+            return isManagedKioskInternal()
+                    && getPowerManagerInternal().wasDeviceIdleFor(UNATTENDED_MANAGED_KIOSK_MS);
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
     @Override
     public boolean isUnattendedManagedKiosk() {
         if (!mHasFeature) {
             return false;
         }
         enforceManageUsers();
-        long id = mInjector.binderClearCallingIdentity();
-        try {
-            return isManagedKioskInternal()
-                    && getPowerManagerInternal().wasDeviceIdleFor(UNATTENDED_MANAGED_KIOSK_MS);
-        } catch (RemoteException e) {
-            throw new IllegalStateException(e);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked());
     }
 
     /**
@@ -15166,4 +15298,252 @@
         }
         return mInjector.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0) != 0;
     }
+
+    @Override
+    public @PersonalAppSuspensionReason int getPersonalAppsSuspendedReasons(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);
+            final DevicePolicyData userData =
+                    getUserData(getProfileParentId(mInjector.userHandleGetCallingUserId()));
+            if (!userData.mAppsSuspended) {
+                return PERSONAL_APPS_NOT_SUSPENDED;
+            } else {
+                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;
+            }
+        }
+    }
+
+    @Override
+    public void setPersonalAppsSuspended(ComponentName who, boolean suspended) {
+        final int callingUserId = 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(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);
+            }
+        }
+
+        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;
+            }
+        }
+
+        applyPersonalAppsSuspension(profileUserId, shouldSuspend);
+    }
+
+    /**
+     * 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) {
+        Slog.i(LOG_TAG, String.format("%s personal apps for user %d",
+                suspended ? "Suspending" : "Unsuspending", userId));
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            try {
+                final String[] appsToSuspend =
+                        new PersonalAppsSuspensionHelper(mContext, mInjector.getPackageManager())
+                                .getPersonalAppsForSuspension(userId);
+                final String[] failedPackages = mIPackageManager.setPackagesSuspendedAsUser(
+                        appsToSuspend, suspended, null, null, null, PLATFORM_PACKAGE_NAME, userId);
+                if (!ArrayUtils.isEmpty(failedPackages)) {
+                    Slog.wtf(LOG_TAG, String.format("Failed to %s packages: %s",
+                            suspended ? "suspend" : "unsuspend", String.join(",", failedPackages)));
+                }
+            } catch (RemoteException re) {
+                // Shouldn't happen.
+                Slog.e(LOG_TAG, "Failed talking to the package manager", re);
+            }
+        });
+
+        synchronized (getLockObject()) {
+            getUserData(userId).mAppsSuspended = suspended;
+            saveSettingsLocked(userId);
+        }
+    }
+
+    private void clearPersonalAppsSuspendedNotification() {
+        mInjector.binderWithCleanCallingIdentity(() ->
+                mInjector.getNotificationManager().cancel(
+                        SystemMessage.NOTE_PERSONAL_APPS_SUSPENDED));
+    }
+
+    private void sendPersonalAppsSuspendedNotification(int userId) {
+        final String profileOwnerPackageName;
+        synchronized (getLockObject()) {
+            profileOwnerPackageName = mOwners.getProfileOwnerComponent(userId).getPackageName();
+        }
+
+        final Intent intent = new Intent(DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE);
+        intent.setPackage(profileOwnerPackageName);
+
+        final PendingIntent pendingIntent = mInjector.pendingIntentGetActivityAsUser(mContext,
+                0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT, null /* options */,
+                UserHandle.of(userId));
+
+        final Notification notification =
+                new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
+                        .setSmallIcon(android.R.drawable.stat_sys_warning)
+                        .setOngoing(true)
+                        .setContentTitle(
+                                mContext.getString(
+                                        R.string.personal_apps_suspended_notification_title))
+                        .setContentText(mContext.getString(
+                                R.string.personal_apps_suspended_notification_text))
+                        .setColor(mContext.getColor(R.color.system_notification_accent_color))
+                        .setContentIntent(pendingIntent)
+                        .build();
+        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/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
new file mode 100644
index 0000000..180acc8
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Slog;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManager;
+import android.view.inputmethod.InputMethodInfo;
+
+import com.android.internal.R;
+import com.android.server.inputmethod.InputMethodManagerInternal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Utility class to find what personal apps should be suspended to limit personal device use.
+ */
+public class PersonalAppsSuspensionHelper {
+    private static final String LOG_TAG = DevicePolicyManagerService.LOG_TAG;
+
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+
+    public PersonalAppsSuspensionHelper(Context context, PackageManager packageManager) {
+        mContext = context;
+        mPackageManager = packageManager;
+    }
+
+    /**
+     * @return List of packages that should be suspended to limit personal use.
+     */
+    String[] getPersonalAppsForSuspension(@UserIdInt int userId) {
+        final List<PackageInfo> installedPackageInfos =
+                mPackageManager.getInstalledPackagesAsUser(0 /* flags */, userId);
+        final Set<String> result = new HashSet<>();
+        for (final PackageInfo packageInfo : installedPackageInfos) {
+            final ApplicationInfo info = packageInfo.applicationInfo;
+            if ((!info.isSystemApp() && !info.isUpdatedSystemApp())
+                    || hasLauncherIntent(packageInfo.packageName)) {
+                result.add(packageInfo.packageName);
+            }
+        }
+        result.removeAll(getCriticalPackages());
+        result.removeAll(getSystemLauncherPackages());
+        result.removeAll(getAccessibilityServices(userId));
+        result.removeAll(getInputMethodPackages(userId));
+        result.remove(getActiveLauncherPackages(userId));
+        result.remove(getDialerPackage(userId));
+        result.remove(getSettingsPackageName(userId));
+
+        Slog.i(LOG_TAG, "Packages subject to suspension: " + String.join(",", result));
+        return result.toArray(new String[0]);
+    }
+
+    private List<String> getSystemLauncherPackages() {
+        final List<String> result = new ArrayList<>();
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_HOME);
+        final List<ResolveInfo> matchingActivities =
+                mPackageManager.queryIntentActivities(intent, 0);
+        for (final ResolveInfo resolveInfo : matchingActivities) {
+            if (resolveInfo.activityInfo == null
+                    || TextUtils.isEmpty(resolveInfo.activityInfo.packageName)) {
+                Slog.wtf(LOG_TAG, "Could not find package name for launcher app" + resolveInfo);
+                continue;
+            }
+            final String packageName = resolveInfo.activityInfo.packageName;
+            try {
+                final ApplicationInfo applicationInfo =
+                        mPackageManager.getApplicationInfo(packageName, 0);
+                if (applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp()) {
+                    Log.d(LOG_TAG, "Not suspending system launcher package: " + packageName);
+                    result.add(packageName);
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.e(LOG_TAG, "Could not find application info for launcher app: " + packageName);
+            }
+        }
+        return result;
+    }
+
+    private List<String> getAccessibilityServices(int userId) {
+        final List<AccessibilityServiceInfo> accessibilityServiceInfos =
+                getAccessibilityManagerForUser(userId)
+                        .getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
+        final List<String> result = new ArrayList<>();
+        for (final AccessibilityServiceInfo serviceInfo : accessibilityServiceInfos) {
+            final ComponentName componentName =
+                    ComponentName.unflattenFromString(serviceInfo.getId());
+            if (componentName != null) {
+                final String packageName = componentName.getPackageName();
+                Slog.d(LOG_TAG, "Not suspending a11y service: " + packageName);
+                result.add(packageName);
+            }
+        }
+        return result;
+    }
+
+    private List<String> getInputMethodPackages(int userId) {
+        final List<InputMethodInfo> enabledImes =
+                InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId);
+        final List<String> result = new ArrayList<>();
+        for (final InputMethodInfo info : enabledImes) {
+            Slog.d(LOG_TAG, "Not suspending IME: " + info.getPackageName());
+            result.add(info.getPackageName());
+        }
+        return result;
+    }
+
+    @Nullable
+    private String getActiveLauncherPackages(int userId) {
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_HOME);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        return getPackageNameForIntent("active launcher", intent, userId);
+    }
+
+    @Nullable
+    private String getSettingsPackageName(int userId) {
+        final Intent intent = new Intent(Settings.ACTION_SETTINGS);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        return getPackageNameForIntent("settings", intent, userId);
+    }
+
+    @Nullable
+    private String getDialerPackage(int userId) {
+        final Intent intent = new Intent(Intent.ACTION_DIAL);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        return getPackageNameForIntent("dialer", intent, userId);
+    }
+
+    @Nullable
+    private String getPackageNameForIntent(String name, Intent intent, int userId) {
+        final ResolveInfo resolveInfo =
+                mPackageManager.resolveActivityAsUser(intent, /* flags= */ 0, userId);
+        if (resolveInfo != null) {
+            final String packageName = resolveInfo.activityInfo.packageName;
+            Slog.d(LOG_TAG, "Not suspending " + name + " package: " + packageName);
+            return packageName;
+        }
+        return null;
+    }
+
+    private List<String> getCriticalPackages() {
+        final List<String> result = Arrays.asList(mContext.getResources()
+                .getStringArray(R.array.config_packagesExemptFromSuspension));
+        Slog.d(LOG_TAG, "Not suspending critical packages: " + String.join(",", result));
+        return result;
+    }
+
+    private boolean hasLauncherIntent(String packageName) {
+        final Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+        intentToResolve.setPackage(packageName);
+        final List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(
+                intentToResolve, PackageManager.GET_UNINSTALLED_PACKAGES);
+        return resolveInfos != null && !resolveInfos.isEmpty();
+    }
+
+    private AccessibilityManager getAccessibilityManagerForUser(int userId) {
+        final IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+        final IAccessibilityManager service =
+                iBinder == null ? null : IAccessibilityManager.Stub.asInterface(iBinder);
+        return new AccessibilityManager(mContext, service, userId);
+    }
+}
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index ec56e1e..62ff3a1 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -96,6 +96,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
+import android.util.FeatureFlagUtils;
 import android.util.Pair;
 
 import com.android.internal.backup.IBackupTransport;
@@ -258,6 +259,9 @@
     public void tearDown() throws Exception {
         ShadowBackupDataInput.reset();
         ShadowApplicationPackageManager.reset();
+        // False by default.
+        FeatureFlagUtils.setEnabled(
+                mContext, FeatureFlagUtils.BACKUP_NO_KV_DATA_CHANGE_CALLS, false);
     }
 
     @Test
@@ -2344,6 +2348,9 @@
     @Test
     public void testRunTask_whenNoDataToBackupOnFirstBackup_doesNotTellTransportOfBackup()
             throws Exception {
+        FeatureFlagUtils.setEnabled(
+                mContext, FeatureFlagUtils.BACKUP_NO_KV_DATA_CHANGE_CALLS, true);
+
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         mBackupManagerService.setCurrentToken(0L);
         when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
@@ -2361,6 +2368,9 @@
     @Test
     public void testRunTask_whenBackupHasCompletedAndThenNoDataChanges_transportGetsNotified()
             throws Exception {
+        FeatureFlagUtils.setEnabled(
+                mContext, FeatureFlagUtils.BACKUP_NO_KV_DATA_CHANGE_CALLS, true);
+
         TransportMock transportMock = setUpInitializedTransport(mTransport);
         when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
         when(transportMock.transport.isAppEligibleForBackup(
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index b3b5af0..0e24b03 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.HARDWARE_TEST"/>
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.MANAGE_APPOPS"/>
+    <uses-permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"/>
 
     <application android:testOnly="true"
                  android:debuggable="true">
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index c3602f8..2080fdf 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -30,11 +30,14 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.times;
 
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.VersionedPackage;
+import android.os.Bundle;
 import android.os.RecoverySystem;
+import android.os.RemoteCallback;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
@@ -44,18 +47,21 @@
 import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
 import com.android.server.RescueParty.RescuePartyObserver;
 import com.android.server.am.SettingsToPropertiesMapper;
-import com.android.server.utils.FlagNamespaceUtils;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Answer;
 
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * Test RescueParty.
@@ -69,16 +75,25 @@
 
     private static VersionedPackage sFailingPackage = new VersionedPackage("com.package.name", 1);
     private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue";
+    private static final String CALLING_PACKAGE1 = "com.package.name1";
+    private static final String CALLING_PACKAGE2 = "com.package.name2";
+    private static final String NAMESPACE1 = "namespace1";
+    private static final String NAMESPACE2 = "namespace2";
 
     private MockitoSession mSession;
+    private HashMap<String, String> mSystemSettingsMap;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mMockContext;
-
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PackageWatchdog mMockPackageWatchdog;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private ContentResolver mMockContentResolver;
 
-    private HashMap<String, String> mSystemSettingsMap;
+    @Captor
+    private ArgumentCaptor<RemoteCallback> mMonitorCallbackCaptor;
+    @Captor
+    private ArgumentCaptor<List<String>> mPackageListCaptor;
 
     @Before
     public void setUp() throws Exception {
@@ -90,14 +105,17 @@
                         .spyStatic(SystemProperties.class)
                         .spyStatic(Settings.Global.class)
                         .spyStatic(Settings.Secure.class)
+                        .spyStatic(Settings.Config.class)
                         .spyStatic(SettingsToPropertiesMapper.class)
                         .spyStatic(RecoverySystem.class)
                         .spyStatic(RescueParty.class)
+                        .spyStatic(PackageWatchdog.class)
                         .startMocking();
         mSystemSettingsMap = new HashMap<>();
 
         when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
-
+        // Reset observer instance to get new mock context on every run
+        RescuePartyObserver.reset();
 
         // Mock SystemProperties setter and various getters
         doAnswer((Answer<Void>) invocationOnMock -> {
@@ -143,9 +161,11 @@
         doAnswer((Answer<Void>) invocationOnMock -> null)
                 .when(() -> DeviceConfig.resetToDefaults(anyInt(), anyString()));
 
+        // Mock PackageWatchdog
+        doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog)
+                .when(() -> PackageWatchdog.getInstance(mMockContext));
 
         doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
-        FlagNamespaceUtils.resetKnownResetNamespacesFlagCounterForTest();
 
         SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL,
                 Integer.toString(RescueParty.LEVEL_NONE));
@@ -162,19 +182,19 @@
     public void testBootLoopDetectionWithExecutionForAllRescueLevels() {
         noteBoot();
 
-        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
         noteBoot();
 
-        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
         noteBoot();
 
-        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS);
+        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
@@ -189,19 +209,19 @@
     public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
         notePersistentAppCrash();
 
-        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
         notePersistentAppCrash();
 
-        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
         notePersistentAppCrash();
 
-        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS);
+        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
 
@@ -213,6 +233,54 @@
     }
 
     @Test
+    public void testNonPersistentAppCrashDetectionWithScopedResets() {
+        RescueParty.onSettingsProviderPublished(mMockContext);
+        verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver),
+                mMonitorCallbackCaptor.capture()));
+
+        // Record DeviceConfig accesses
+        RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
+        RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue();
+        monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1));
+        monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2));
+        monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE2));
+        // Fake DeviceConfig value changes
+        monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1));
+        verify(mMockPackageWatchdog).startObservingHealth(observer,
+                Arrays.asList(CALLING_PACKAGE1), RescueParty.DEFAULT_OBSERVING_DURATION_MS);
+        monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE2));
+        verify(mMockPackageWatchdog, times(2)).startObservingHealth(eq(observer),
+                mPackageListCaptor.capture(),
+                eq(RescueParty.DEFAULT_OBSERVING_DURATION_MS));
+        assertTrue(mPackageListCaptor.getValue().containsAll(
+                Arrays.asList(CALLING_PACKAGE1, CALLING_PACKAGE2)));
+        // Perform and verify scoped resets
+        final String[] expectedResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2};
+        observer.execute(new VersionedPackage(
+                CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, expectedResetNamespaces);
+        assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
+                SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+        observer.execute(new VersionedPackage(
+                CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, expectedResetNamespaces);
+        assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
+                SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+        observer.execute(new VersionedPackage(
+                CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+        verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/null);
+        assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
+                SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+
+        observer.execute(new VersionedPackage(
+                CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+        verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
+        assertTrue(RescueParty.isAttemptingFactoryReset());
+    }
+
+    @Test
     public void testIsAttemptingFactoryReset() {
         for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
             noteBoot();
@@ -227,7 +295,7 @@
 
         RescueParty.onSettingsProviderPublished(mMockContext);
 
-        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS);
+        verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
         assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
                 SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
     }
@@ -244,15 +312,6 @@
                 FAKE_NATIVE_NAMESPACE1));
         verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
                 FAKE_NATIVE_NAMESPACE2));
-
-        ExtendedMockito.verify(
-                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
-                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 0,
-                        FAKE_NATIVE_NAMESPACE1, /*makeDefault=*/true));
-        ExtendedMockito.verify(
-                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
-                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 1,
-                        FAKE_NATIVE_NAMESPACE2, /*makeDefault=*/true));
     }
 
     @Test
@@ -326,11 +385,19 @@
                 RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS);
     }
 
-    private void verifySettingsResets(int resetMode) {
+    private void verifySettingsResets(int resetMode, String[] resetNamespaces) {
         verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
                 resetMode, UserHandle.USER_SYSTEM));
         verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
                 eq(resetMode), anyInt()));
+        // Verify DeviceConfig resets
+        if (resetNamespaces == null) {
+            verify(() -> DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null));
+        } else {
+            for (String namespace : resetNamespaces) {
+                verify(() -> DeviceConfig.resetToDefaults(resetMode, namespace));
+            }
+        }
     }
 
     private void noteBoot() {
@@ -339,6 +406,22 @@
 
     private void notePersistentAppCrash() {
         RescuePartyObserver.getInstance(mMockContext).execute(new VersionedPackage(
-                "com.package.name", 1), PackageWatchdog.FAILURE_REASON_UNKNOWN);
+                "com.package.name", 1), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+    }
+
+    private Bundle getConfigAccessBundle(String callingPackage, String namespace) {
+        Bundle result = new Bundle();
+        result.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, Settings.EXTRA_ACCESS_CALLBACK);
+        result.putString(Settings.EXTRA_CALLING_PACKAGE, callingPackage);
+        result.putString(Settings.EXTRA_NAMESPACE, namespace);
+        return result;
+    }
+
+    private Bundle getConfigNamespaceUpdateBundle(String updatedNamespace) {
+        Bundle result = new Bundle();
+        result.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE,
+                Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK);
+        result.putString(Settings.EXTRA_NAMESPACE, updatedNamespace);
+        return result;
     }
 }
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/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..9a63393 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -57,7 +57,6 @@
 import android.os.Message;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
 import com.android.server.LocalServices;
@@ -68,6 +67,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 +81,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 +91,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 +110,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;
@@ -173,7 +176,8 @@
         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 +195,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 +215,8 @@
         makeUsSystemApp();
         Rule rule =
                 new Rule(
-                        new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+                        new AtomicFormula.BooleanAtomicFormula(
+                                AtomicFormula.PRE_INSTALLED, true),
                         Rule.DENY);
 
         // no SecurityException
@@ -447,7 +453,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..9915702 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
@@ -50,7 +50,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;
 
@@ -70,29 +71,29 @@
         assertEquals(
                 IntegrityCheckResult.Effect.ALLOW,
                 mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
+                        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)
+                        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)
+                        getAppInstallMetadataBuilder()
+                                .setInstallerName(RANDOM_INSTALLER)
+                                .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+                                .build(),
+                        allowedInstallers)
                         .getEffect());
     }
 
@@ -104,38 +105,38 @@
         assertEquals(
                 IntegrityCheckResult.Effect.ALLOW,
                 mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
+                        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)
+                        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)
+                        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)
+                        getAppInstallMetadataBuilder()
+                                .setInstallerName(RANDOM_INSTALLER)
+                                .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+                                .build(),
+                        allowedInstallers)
                         .getEffect());
     }
 
@@ -149,38 +150,38 @@
         assertEquals(
                 IntegrityCheckResult.Effect.ALLOW,
                 mEngine.evaluate(
-                                getAppInstallMetadataBuilder()
-                                        .setInstallerName(INSTALLER_1)
-                                        .setInstallerCertificate(INSTALLER_1_CERT)
-                                        .build(),
-                                allowedInstallers)
+                        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)
+                        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)
+                        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)
+                        getAppInstallMetadataBuilder()
+                                .setInstallerName(INSTALLER_2)
+                                .setInstallerCertificate(INSTALLER_1_CERT)
+                                .build(),
+                        allowedInstallers)
                         .getEffect());
     }
 
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..629fd14 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,7 +58,7 @@
 
         IntegrityCheckResult result = RuleEvaluator.evaluateRules(rules, APP_INSTALL_METADATA);
 
-        assertEquals(ALLOW, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
     }
 
     @Test
@@ -73,7 +74,7 @@
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule1), 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.getRule()).isEqualTo(rule1);
     }
 
     @Test
@@ -126,8 +127,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.getRule()).isEqualTo(rule1);
     }
 
     @Test
@@ -145,23 +146,23 @@
         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.getRule()).isEqualTo(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.getRule()).isEqualTo(rule);
     }
 
     @Test
@@ -183,8 +184,8 @@
         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.getRule()).isEqualTo(rule);
     }
 
     @Test
@@ -206,7 +207,7 @@
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(DENY);
     }
 
     @Test
@@ -230,7 +231,7 @@
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
-        assertEquals(DENY, result.getEffect());
+        assertThat(result.getEffect()).isEqualTo(DENY);
     }
 
     @Test
@@ -259,7 +260,7 @@
         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.getRule()).isEqualTo(rule1);
     }
-}
+}
\ No newline at end of file
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/lights/LightsServiceTest.java b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
new file mode 100644
index 0000000..b0def60
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/lights/LightsServiceTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.lights;
+
+import static android.hardware.lights.LightsRequest.Builder;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.hardware.light.HwLight;
+import android.hardware.light.HwLightState;
+import android.hardware.light.ILights;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+import android.hardware.lights.LightsManager;
+import android.os.Looper;
+
+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;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LightsServiceTest {
+
+    private final ILights mHal = new ILights.Stub() {
+        @Override
+        public void setLightState(int id, HwLightState state) {
+            return;
+        }
+
+        @Override
+        public HwLight[] getLights() {
+            return new HwLight[] {
+                fakeHwLight(101, 3, 1),
+                fakeHwLight(102, LightsManager.LIGHT_TYPE_MICROPHONE, 4),
+                fakeHwLight(103, LightsManager.LIGHT_TYPE_MICROPHONE, 3),
+                fakeHwLight(104, LightsManager.LIGHT_TYPE_MICROPHONE, 1),
+                fakeHwLight(105, LightsManager.LIGHT_TYPE_MICROPHONE, 2)
+            };
+        }
+    };
+
+    private static HwLight fakeHwLight(int id, int type, int ordinal) {
+        HwLight light = new HwLight();
+        light.id = id;
+        light.type = (byte) type;
+        light.ordinal = ordinal;
+        return light;
+    }
+
+    @Mock
+    Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void testGetLights_filtersSystemLights() {
+        LightsService service = new LightsService(mContext, mHal, Looper.getMainLooper());
+        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+
+        // When lights are listed, only the 4 MICROPHONE lights should be visible.
+        assertThat(manager.getLights().size()).isEqualTo(4);
+    }
+
+    @Test
+    public void testControlMultipleLights() {
+        LightsService service = new LightsService(mContext, mHal, Looper.getMainLooper());
+        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+
+        // When the session requests to turn 3/4 lights on:
+        LightsManager.LightsSession session = manager.openSession();
+        session.setLights(new Builder()
+                .setLight(manager.getLights().get(0), new LightState(0xf1))
+                .setLight(manager.getLights().get(1), new LightState(0xf2))
+                .setLight(manager.getLights().get(2), new LightState(0xf3))
+                .build());
+
+        // Then all 3 should turn on.
+        assertThat(manager.getLightState(manager.getLights().get(0)).getColor()).isEqualTo(0xf1);
+        assertThat(manager.getLightState(manager.getLights().get(1)).getColor()).isEqualTo(0xf2);
+        assertThat(manager.getLightState(manager.getLights().get(2)).getColor()).isEqualTo(0xf3);
+
+        // And the 4th should remain off.
+        assertThat(manager.getLightState(manager.getLights().get(3)).getColor()).isEqualTo(0x00);
+    }
+
+    @Test
+    public void testControlLights_onlyEffectiveForLifetimeOfClient() {
+        LightsService service = new LightsService(mContext, mHal, Looper.getMainLooper());
+        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        Light micLight = manager.getLights().get(0);
+
+        // The light should begin by being off.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0x00000000);
+
+        // When a session commits changes:
+        LightsManager.LightsSession session = manager.openSession();
+        session.setLights(new Builder().setLight(micLight, new LightState(0xff00ff00)).build());
+        // Then the light should turn on.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0xff00ff00);
+
+        // When the session goes away:
+        session.close();
+        // Then the light should turn off.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0x00000000);
+    }
+
+    @Test
+    public void testControlLights_firstCallerWinsContention() {
+        LightsService service = new LightsService(mContext, mHal, Looper.getMainLooper());
+        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        Light micLight = manager.getLights().get(0);
+
+        LightsManager.LightsSession session1 = manager.openSession();
+        LightsManager.LightsSession session2 = manager.openSession();
+
+        // When session1 and session2 both request the same light:
+        session1.setLights(new Builder().setLight(micLight, new LightState(0xff0000ff)).build());
+        session2.setLights(new Builder().setLight(micLight, new LightState(0xffffffff)).build());
+        // Then session1 should win because it was created first.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0xff0000ff);
+
+        // When session1 goes away:
+        session1.close();
+        // Then session2 should have its request go into effect.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0xffffffff);
+
+        // When session2 goes away:
+        session2.close();
+        // Then the light should turn off because there are no more sessions.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0);
+    }
+
+    @Test
+    public void testClearLight() {
+        LightsService service = new LightsService(mContext, mHal, Looper.getMainLooper());
+        LightsManager manager = new LightsManager(mContext, service.mManagerService);
+        Light micLight = manager.getLights().get(0);
+
+        // When the session turns a light on:
+        LightsManager.LightsSession session = manager.openSession();
+        session.setLights(new Builder().setLight(micLight, new LightState(0xffffffff)).build());
+
+        // And then the session clears it again:
+        session.setLights(new Builder().clearLight(micLight).build());
+
+        // Then the light should turn back off.
+        assertThat(manager.getLightState(micLight).getColor()).isEqualTo(0);
+    }
+}
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 15327b6..a8674a8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -309,6 +309,7 @@
                 actual.getStagedSessionErrorMessage());
         assertEquals(expected.isPrepared(), actual.isPrepared());
         assertEquals(expected.isCommitted(), actual.isCommitted());
+        assertEquals(expected.createdMillis, actual.createdMillis);
         assertEquals(expected.isSealed(), actual.isSealed());
         assertEquals(expected.isMultiPackage(), actual.isMultiPackage());
         assertEquals(expected.hasParentSessionId(), actual.hasParentSessionId());
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/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/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/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 1e55b15..651ad40 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -74,7 +74,7 @@
 
 import com.android.internal.util.IntPair;
 import com.android.server.UiServiceTestCase;
-import com.android.server.lights.Light;
+import com.android.server.lights.LogicalLight;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -91,13 +91,14 @@
     @Mock AudioManager mAudioManager;
     @Mock Vibrator mVibrator;
     @Mock android.media.IRingtonePlayer mRingtonePlayer;
-    @Mock Light mLight;
+    @Mock LogicalLight mLight;
     @Mock
     NotificationManagerService.WorkerHandler mHandler;
     @Mock
     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 9260fbf..1b92abe 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -153,8 +153,8 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.UiServiceTestCase;
-import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
 import com.android.server.notification.NotificationManagerService.NotificationAssistants;
 import com.android.server.notification.NotificationManagerService.NotificationListeners;
 import com.android.server.uri.UriGrantsManagerInternal;
@@ -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);
@@ -372,7 +374,7 @@
                 });
         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
         final LightsManager mockLightsManager = mock(LightsManager.class);
-        when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
+        when(mockLightsManager.getLight(anyInt())).thenReturn(mock(LogicalLight.class));
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
@@ -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));
     }
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/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 0527561..5ba676d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -36,7 +36,6 @@
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -141,7 +140,7 @@
     public void layoutWindowLw_fitStatusBars() {
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.statusBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.statusBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -159,7 +158,7 @@
     public void layoutWindowLw_fitNavigationBars() {
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.navigationBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.navigationBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -178,7 +177,7 @@
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
         mWindow.mAttrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.systemBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -197,7 +196,7 @@
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
         mWindow.mAttrs.privateFlags = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.systemBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -216,8 +215,7 @@
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
         mWindow.mAttrs.flags = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-        mWindow.mAttrs.privateFlags = PRIVATE_FLAG_ONLY_DRAW_BOTTOM_BAR_BACKGROUND;
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.systemBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -235,7 +233,7 @@
     public void layoutWindowLw_fitAllSides() {
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
-        mWindow.mAttrs.setFitWindowInsetsSides(Side.all());
+        mWindow.mAttrs.setFitInsetsSides(Side.all());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -253,7 +251,7 @@
     public void layoutWindowLw_fitTopOnly() {
         assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
 
-        mWindow.mAttrs.setFitWindowInsetsSides(Side.TOP);
+        mWindow.mAttrs.setFitInsetsSides(Side.TOP);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -275,7 +273,7 @@
                 mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
-        mWindow.mAttrs.setFitIgnoreVisibility(true);
+        mWindow.mAttrs.setFitInsetsIgnoringVisibility(true);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -297,7 +295,7 @@
                 mDisplayContent.getInsetsPolicy().getInsetsForDispatch(mWindow);
         state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false);
         state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false);
-        mWindow.mAttrs.setFitIgnoreVisibility(false);
+        mWindow.mAttrs.setFitInsetsIgnoringVisibility(false);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -374,7 +372,7 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-        mWindow.mAttrs.setFitWindowInsetsTypes(0 /* types */);
+        mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* uiMode */);
@@ -431,8 +429,8 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-        mWindow.mAttrs.setFitWindowInsetsTypes(
-                mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
+        mWindow.mAttrs.setFitInsetsTypes(
+                mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -537,8 +535,8 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-        mWindow.mAttrs.setFitWindowInsetsTypes(
-                mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
+        mWindow.mAttrs.setFitInsetsTypes(
+                mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -556,7 +554,7 @@
         addDisplayCutout();
 
         mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN;
-        mWindow.mAttrs.setFitWindowInsetsTypes(Type.systemBars() & ~Type.statusBars());
+        mWindow.mAttrs.setFitInsetsTypes(Type.systemBars() & ~Type.statusBars());
         mWindow.mAttrs.type = TYPE_APPLICATION_OVERLAY;
         mWindow.mAttrs.width = DISPLAY_WIDTH;
         mWindow.mAttrs.height = DISPLAY_HEIGHT;
@@ -577,8 +575,8 @@
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
         mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
-        mWindow.mAttrs.setFitWindowInsetsTypes(
-                mWindow.mAttrs.getFitWindowInsetsTypes() & ~Type.statusBars());
+        mWindow.mAttrs.setFitInsetsTypes(
+                mWindow.mAttrs.getFitInsetsTypes() & ~Type.statusBars());
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         addWindow(mWindow);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index e699b52..c370d6c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -28,6 +28,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -233,6 +234,16 @@
         assertNotEquals(0, toast.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED);
     }
 
+    @Test(expected = RuntimeException.class)
+    public void testMainAppWindowDisallowFitSystemWindowTypes() {
+        final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
+        final WindowState activity = createBaseApplicationWindow();
+        activity.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+
+        policy.adjustWindowParamsLw(activity, activity.mAttrs, 0 /* callingPid */,
+                0 /* callingUid */);
+    }
+
     private WindowState createToastWindow() {
         final WindowState win = createWindow(null, TYPE_TOAST, "Toast");
         final WindowManager.LayoutParams attrs = win.mAttrs;
@@ -254,6 +265,17 @@
         return win;
     }
 
+    private WindowState createBaseApplicationWindow() {
+        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "Application");
+        final WindowManager.LayoutParams attrs = win.mAttrs;
+        attrs.width = MATCH_PARENT;
+        attrs.height = MATCH_PARENT;
+        attrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+        attrs.format = PixelFormat.OPAQUE;
+        win.mHasSurface = true;
+        return win;
+    }
+
     @Test
     @FlakyTest(bugId = 131005232)
     public void testOverlappingWithNavBar() {
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/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/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/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index c58b6da..af81ab6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -46,18 +46,21 @@
     private static final String NAME = "sound_model.db";
     private static final int VERSION = 7;
 
-    public static interface SoundModelContract {
-        public static final String TABLE = "sound_model";
-        public static final String KEY_MODEL_UUID = "model_uuid";
-        public static final String KEY_VENDOR_UUID = "vendor_uuid";
-        public static final String KEY_KEYPHRASE_ID = "keyphrase_id";
-        public static final String KEY_TYPE = "type";
-        public static final String KEY_DATA = "data";
-        public static final String KEY_RECOGNITION_MODES = "recognition_modes";
-        public static final String KEY_LOCALE = "locale";
-        public static final String KEY_HINT_TEXT = "hint_text";
-        public static final String KEY_USERS = "users";
-        public static final String KEY_MODEL_VERSION = "model_version";
+    /**
+     * Keyphrase sound model database columns
+     */
+    public interface SoundModelContract {
+        String TABLE = "sound_model";
+        String KEY_MODEL_UUID = "model_uuid";
+        String KEY_VENDOR_UUID = "vendor_uuid";
+        String KEY_KEYPHRASE_ID = "keyphrase_id";
+        String KEY_TYPE = "type";
+        String KEY_DATA = "data";
+        String KEY_RECOGNITION_MODES = "recognition_modes";
+        String KEY_LOCALE = "locale";
+        String KEY_HINT_TEXT = "hint_text";
+        String KEY_USERS = "users";
+        String KEY_MODEL_VERSION = "model_version";
     }
 
     // Table Create Statement
@@ -173,7 +176,8 @@
                         soundModel.keyphrases[0].recognitionModes);
                 values.put(SoundModelContract.KEY_USERS,
                         getCommaSeparatedString(soundModel.keyphrases[0].users));
-                values.put(SoundModelContract.KEY_LOCALE, soundModel.keyphrases[0].locale);
+                values.put(SoundModelContract.KEY_LOCALE,
+                        soundModel.keyphrases[0].locale.toLanguageTag());
                 values.put(SoundModelContract.KEY_HINT_TEXT, soundModel.keyphrases[0].text);
                 try {
                     return db.insertWithOnConflict(SoundModelContract.TABLE, null, values,
@@ -190,7 +194,7 @@
      * Deletes the sound model and associated keyphrases.
      */
     public boolean deleteKeyphraseSoundModel(int keyphraseId, int userHandle, String bcp47Locale) {
-        // Sanitize the locale to guard against SQL injection.
+        // Normalize the locale to guard against SQL injection.
         bcp47Locale = Locale.forLanguageTag(bcp47Locale).toLanguageTag();
         synchronized(this) {
             KeyphraseSoundModel soundModel = getKeyphraseSoundModel(keyphraseId, userHandle,
@@ -226,92 +230,119 @@
             String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE
                     + " WHERE " + SoundModelContract.KEY_KEYPHRASE_ID + "= '" + keyphraseId
                     + "' AND " + SoundModelContract.KEY_LOCALE + "='" + bcp47Locale + "'";
-            SQLiteDatabase db = getReadableDatabase();
-            Cursor c = db.rawQuery(selectQuery, null);
-
-            try {
-                if (c.moveToFirst()) {
-                    do {
-                        int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
-                        if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
-                            if (DBG) {
-                                Slog.w(TAG, "Ignoring SoundModel since it's type is incorrect");
-                            }
-                            continue;
-                        }
-
-                        String modelUuid = c.getString(
-                                c.getColumnIndex(SoundModelContract.KEY_MODEL_UUID));
-                        if (modelUuid == null) {
-                            Slog.w(TAG, "Ignoring SoundModel since it doesn't specify an ID");
-                            continue;
-                        }
-
-                        String vendorUuidString = null;
-                        int vendorUuidColumn = c.getColumnIndex(SoundModelContract.KEY_VENDOR_UUID);
-                        if (vendorUuidColumn != -1) {
-                            vendorUuidString = c.getString(vendorUuidColumn);
-                        }
-                        byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
-                        int recognitionModes = c.getInt(
-                                c.getColumnIndex(SoundModelContract.KEY_RECOGNITION_MODES));
-                        int[] users = getArrayForCommaSeparatedString(
-                                c.getString(c.getColumnIndex(SoundModelContract.KEY_USERS)));
-                        String modelLocale = c.getString(
-                                c.getColumnIndex(SoundModelContract.KEY_LOCALE));
-                        String text = c.getString(
-                                c.getColumnIndex(SoundModelContract.KEY_HINT_TEXT));
-                        int version = c.getInt(
-                                c.getColumnIndex(SoundModelContract.KEY_MODEL_VERSION));
-
-                        // Only add keyphrases meant for the current user.
-                        if (users == null) {
-                            // No users present in the keyphrase.
-                            Slog.w(TAG, "Ignoring SoundModel since it doesn't specify users");
-                            continue;
-                        }
-
-                        boolean isAvailableForCurrentUser = false;
-                        for (int user : users) {
-                            if (userHandle == user) {
-                                isAvailableForCurrentUser = true;
-                                break;
-                            }
-                        }
-                        if (!isAvailableForCurrentUser) {
-                            if (DBG) {
-                                Slog.w(TAG, "Ignoring SoundModel since user handles don't match");
-                            }
-                            continue;
-                        } else {
-                            if (DBG) Slog.d(TAG, "Found a SoundModel for user: " + userHandle);
-                        }
-
-                        Keyphrase[] keyphrases = new Keyphrase[1];
-                        keyphrases[0] = new Keyphrase(
-                                keyphraseId, recognitionModes, modelLocale, text, users);
-                        UUID vendorUuid = null;
-                        if (vendorUuidString != null) {
-                            vendorUuid = UUID.fromString(vendorUuidString);
-                        }
-                        KeyphraseSoundModel model = new KeyphraseSoundModel(
-                                UUID.fromString(modelUuid), vendorUuid, data, keyphrases, version);
-                        if (DBG) {
-                            Slog.d(TAG, "Found SoundModel for the given keyphrase/locale/user: "
-                                    + model);
-                        }
-                        return model;
-                    } while (c.moveToNext());
-                }
-                Slog.w(TAG, "No SoundModel available for the given keyphrase");
-            } finally {
-                c.close();
-                db.close();
-            }
-            return null;
+            return getValidKeyphraseSoundModelForUser(selectQuery, userHandle);
         }
     }
 
+    /**
+     * Returns a matching {@link KeyphraseSoundModel} for the keyphrase string.
+     * Returns null if a match isn't found.
+     *
+     * TODO: We only support one keyphrase currently.
+     */
+    public KeyphraseSoundModel getKeyphraseSoundModel(String keyphrase, int userHandle,
+            String bcp47Locale) {
+        // Sanitize the locale to guard against SQL injection.
+        bcp47Locale = Locale.forLanguageTag(bcp47Locale).toLanguageTag();
+        synchronized (this) {
+            // Find the corresponding sound model ID for the keyphrase.
+            String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE
+                    + " WHERE " + SoundModelContract.KEY_HINT_TEXT + "= '" + keyphrase
+                    + "' AND " + SoundModelContract.KEY_LOCALE + "='" + bcp47Locale + "'";
+            return getValidKeyphraseSoundModelForUser(selectQuery, userHandle);
+        }
+    }
+
+    private KeyphraseSoundModel getValidKeyphraseSoundModelForUser(String selectQuery,
+            int userHandle) {
+        SQLiteDatabase db = getReadableDatabase();
+        Cursor c = db.rawQuery(selectQuery, null);
+
+        try {
+            if (c.moveToFirst()) {
+                do {
+                    int type = c.getInt(c.getColumnIndex(SoundModelContract.KEY_TYPE));
+                    if (type != SoundTrigger.SoundModel.TYPE_KEYPHRASE) {
+                        if (DBG) {
+                            Slog.w(TAG, "Ignoring SoundModel since its type is incorrect");
+                        }
+                        continue;
+                    }
+
+                    String modelUuid = c.getString(
+                            c.getColumnIndex(SoundModelContract.KEY_MODEL_UUID));
+                    if (modelUuid == null) {
+                        Slog.w(TAG, "Ignoring SoundModel since it doesn't specify an ID");
+                        continue;
+                    }
+
+                    String vendorUuidString = null;
+                    int vendorUuidColumn = c.getColumnIndex(SoundModelContract.KEY_VENDOR_UUID);
+                    if (vendorUuidColumn != -1) {
+                        vendorUuidString = c.getString(vendorUuidColumn);
+                    }
+                    int keyphraseId = c.getInt(
+                            c.getColumnIndex(SoundModelContract.KEY_KEYPHRASE_ID));
+                    byte[] data = c.getBlob(c.getColumnIndex(SoundModelContract.KEY_DATA));
+                    int recognitionModes = c.getInt(
+                            c.getColumnIndex(SoundModelContract.KEY_RECOGNITION_MODES));
+                    int[] users = getArrayForCommaSeparatedString(
+                            c.getString(c.getColumnIndex(SoundModelContract.KEY_USERS)));
+                    Locale modelLocale = Locale.forLanguageTag(c.getString(
+                            c.getColumnIndex(SoundModelContract.KEY_LOCALE)));
+                    String text = c.getString(
+                            c.getColumnIndex(SoundModelContract.KEY_HINT_TEXT));
+                    int version = c.getInt(
+                            c.getColumnIndex(SoundModelContract.KEY_MODEL_VERSION));
+
+                    // Only add keyphrases meant for the current user.
+                    if (users == null) {
+                        // No users present in the keyphrase.
+                        Slog.w(TAG, "Ignoring SoundModel since it doesn't specify users");
+                        continue;
+                    }
+
+                    boolean isAvailableForCurrentUser = false;
+                    for (int user : users) {
+                        if (userHandle == user) {
+                            isAvailableForCurrentUser = true;
+                            break;
+                        }
+                    }
+                    if (!isAvailableForCurrentUser) {
+                        if (DBG) {
+                            Slog.w(TAG, "Ignoring SoundModel since user handles don't match");
+                        }
+                        continue;
+                    } else {
+                        if (DBG) Slog.d(TAG, "Found a SoundModel for user: " + userHandle);
+                    }
+
+                    Keyphrase[] keyphrases = new Keyphrase[1];
+                    keyphrases[0] = new Keyphrase(
+                            keyphraseId, recognitionModes, modelLocale, text, users);
+                    UUID vendorUuid = null;
+                    if (vendorUuidString != null) {
+                        vendorUuid = UUID.fromString(vendorUuidString);
+                    }
+                    KeyphraseSoundModel model = new KeyphraseSoundModel(
+                            UUID.fromString(modelUuid), vendorUuid, data, keyphrases, version);
+                    if (DBG) {
+                        Slog.d(TAG, "Found SoundModel for the given keyphrase/locale/user: "
+                                + model);
+                    }
+                    return model;
+                } while (c.moveToNext());
+            }
+            Slog.w(TAG, "No SoundModel available for the given keyphrase");
+        } finally {
+            c.close();
+            db.close();
+        }
+
+        return null;
+    }
+
     private static String getCommaSeparatedString(int[] users) {
         if (users == null) {
             return "";
@@ -431,8 +462,11 @@
         }
     }
 
+    /**
+     * Dumps contents of database for dumpsys
+     */
     public void dump(PrintWriter pw) {
-        synchronized(this) {
+        synchronized (this) {
             String selectQuery = "SELECT  * FROM " + SoundModelContract.TABLE;
             SQLiteDatabase db = getReadableDatabase();
             Cursor c = db.rawQuery(selectQuery, null);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 506c67e..d5eec33 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -41,7 +41,9 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.KeyphraseMetadata;
 import android.hardware.soundtrigger.ModelParams;
+import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
@@ -90,6 +92,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 
@@ -923,6 +926,8 @@
         }
 
         //----------------- Model management APIs --------------------------------//
+        // TODO: add check to only allow active voice interaction service or keyphrase enrollment
+        //       application to manage voice models
 
         @Override
         public KeyphraseSoundModel getKeyphraseSoundModel(int keyphraseId, String bcp47Locale) {
@@ -1022,6 +1027,41 @@
             }
         }
 
+        @Nullable
+        public KeyphraseMetadata getEnrolledKeyphraseMetadata(IVoiceInteractionService service,
+                String keyphrase, String bcp47Locale) {
+            synchronized (this) {
+                enforceIsCurrentVoiceInteractionService(service);
+            }
+
+            if (bcp47Locale == null) {
+                throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
+            }
+
+            final int callingUid = UserHandle.getCallingUserId();
+            final long caller = Binder.clearCallingIdentity();
+            try {
+                KeyphraseSoundModel model =
+                        mDbHelper.getKeyphraseSoundModel(keyphrase, callingUid, bcp47Locale);
+                if (model == null) {
+                    return null;
+                }
+
+                for (SoundTrigger.Keyphrase phrase : model.keyphrases) {
+                    if (keyphrase.equals(phrase.text)) {
+                        ArraySet<Locale> locales = new ArraySet<>();
+                        locales.add(phrase.locale);
+                        return new KeyphraseMetadata(phrase.id, phrase.text, locales,
+                                phrase.recognitionModes);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(caller);
+            }
+
+            return null;
+        }
+
         @Override
         public ModuleProperties getDspModuleProperties(IVoiceInteractionService service) {
             // Allow the call if this is the current voice interaction service.
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/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/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/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 9b82828..32f9d53 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;
@@ -40,7 +41,6 @@
 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;
 
@@ -48,8 +48,6 @@
 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;
 import java.util.List;
@@ -205,7 +203,7 @@
                 < android.os.Process.FIRST_APPLICATION_UID) {
             return contextUserId;
         } else {
-            return UserHandle.getUserId(callingUid);
+            return UserHandle.getUserHandleForUid(callingUid).getIdentifier();
         }
     }
 
@@ -811,10 +809,10 @@
                 // This should never happen in prod -- unit tests will put the receiver into a
                 // unusual state where the pending result is null, which produces a NPE when calling
                 // getSendingUserId. Just pretend like it's the system user for testing.
-                userId = UserHandle.USER_SYSTEM;
+                userId = UserHandle.SYSTEM.getIdentifier();
             }
             Context userContext = mContext;
-            if (userId != UserHandle.USER_SYSTEM) {
+            if (userId != UserHandle.SYSTEM.getIdentifier()) {
                 try {
                     userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
                         UserHandle.of(userId));
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..156c7ad 100644
--- a/telephony/common/com/google/android/mms/util/DrmConvertSession.java
+++ b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
@@ -16,14 +16,13 @@
  */
 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;
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/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index ef11f46..9315586 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -31,7 +31,9 @@
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
+import android.telephony.euicc.EuiccManager;
 import android.telephony.euicc.EuiccManager.OtaStatus;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.PrintWriter;
@@ -311,6 +313,65 @@
         mStubWrapper = new IEuiccServiceWrapper();
     }
 
+    /**
+     * Given a SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2), encode it to
+     * the format described in
+     * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}
+     *
+     * @param subjectCode SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2)
+     * @param reasonCode  ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2)
+     * @return encoded error code described in
+     * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}
+     * @throws NumberFormatException         when the Subject/Reason code contains non digits
+     * @throws IllegalArgumentException      when Subject/Reason code is null/empty
+     * @throws UnsupportedOperationException when sections has more than four layers (e.g 5.8.1.2)
+     *                                       or when an number is bigger than 15
+     */
+    public int encodeSmdxSubjectAndReasonCode(@Nullable String subjectCode,
+            @Nullable String reasonCode)
+            throws NumberFormatException, IllegalArgumentException, UnsupportedOperationException {
+        final int maxSupportedSection = 3;
+        final int maxSupportedDigit = 15;
+        final int bitsPerSection = 4;
+
+        if (TextUtils.isEmpty(subjectCode) || TextUtils.isEmpty(reasonCode)) {
+            throw new IllegalArgumentException("SubjectCode/ReasonCode is empty");
+        }
+
+        final String[] subjectCodeToken = subjectCode.split("\\.");
+        final String[] reasonCodeToken = reasonCode.split("\\.");
+
+        if (subjectCodeToken.length > maxSupportedSection
+                || reasonCodeToken.length > maxSupportedSection) {
+            throw new UnsupportedOperationException("Only three nested layer is supported.");
+        }
+
+        int result = EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE;
+
+        // Pad the 0s needed for subject code
+        result = result << (maxSupportedSection - subjectCodeToken.length) * bitsPerSection;
+
+        for (String digitString : subjectCodeToken) {
+            int num = Integer.parseInt(digitString);
+            if (num > maxSupportedDigit) {
+                throw new UnsupportedOperationException("SubjectCode exceeds " + maxSupportedDigit);
+            }
+            result = (result << bitsPerSection) + num;
+        }
+
+        // Pad the 0s needed for reason code
+        result = result << (maxSupportedSection - reasonCodeToken.length) * bitsPerSection;
+        for (String digitString : reasonCodeToken) {
+            int num = Integer.parseInt(digitString);
+            if (num > maxSupportedDigit) {
+                throw new UnsupportedOperationException("ReasonCode exceeds " + maxSupportedDigit);
+            }
+            result = (result << bitsPerSection) + num;
+        }
+
+        return result;
+    }
+
     @Override
     @CallSuper
     public void onCreate() {
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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 822e55b..945c888 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1454,6 +1454,50 @@
             "apn_settings_default_apn_types_string_array";
 
     /**
+     * Configs used for APN setup.
+     */
+    public static final class Apn {
+        /** Prefix of all Apn.KEY_* constants. */
+        public static final String KEY_PREFIX = "apn.";
+
+        /** IPv4 internet protocol */
+        public static final String PROTOCOL_IPV4 = "IP";
+        /** IPv6 internet protocol */
+        public static final String PROTOCOL_IPV6 = "IPV6";
+        /** IPv4 or IPv6 internet protocol */
+        public static final String PROTOCOL_IPV4V6 = "IPV4V6";
+
+        /**
+         * Default value of APN protocol field if not specified by user when adding/modifying
+         * an APN.
+         *
+         * Available options are: {@link #PROTOCOL_IPV4}, {@link #PROTOCOL_IPV6},
+         * {@link #PROTOCOL_IPV4V6}
+         */
+        public static final String KEY_SETTINGS_DEFAULT_PROTOCOL_STRING =
+                KEY_PREFIX + "settings_default_protocol_string";
+
+        /**
+         * Default value of APN roaming protocol field if not specified by user when
+         * adding/modifying an APN.
+         *
+         * Available options are: {@link #PROTOCOL_IPV4}, {@link #PROTOCOL_IPV6},
+         * {@link #PROTOCOL_IPV4V6}
+         */
+        public static final String KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING =
+                KEY_PREFIX + "settings_default_roaming_protocol_string";
+
+        private Apn() {}
+
+        private static PersistableBundle getDefaults() {
+            PersistableBundle defaults = new PersistableBundle();
+            defaults.putString(KEY_SETTINGS_DEFAULT_PROTOCOL_STRING, "");
+            defaults.putString(KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING, "");
+            return defaults;
+        }
+    }
+
+    /**
      * Boolean indicating if intent for emergency call state changes should be broadcast
      * @hide
      */
@@ -3420,6 +3464,14 @@
             "prevent_clir_activation_and_deactivation_code_bool";
 
     /**
+     * Flag specifying whether to show forwarded number on call-in-progress screen.
+     * When true, forwarded number is shown.
+     * When false, forwarded number is not shown.
+     */
+    public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL =
+            "show_forwarded_number_bool";
+
+    /**
      * Configs used for epdg tunnel bring up.
      *
      * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange
@@ -3903,6 +3955,8 @@
         sDefaults.putStringArray(KEY_READ_ONLY_APN_TYPES_STRING_ARRAY, new String[] {"dun"});
         sDefaults.putStringArray(KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY, null);
+        sDefaults.putAll(Apn.getDefaults());
+
         sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
         sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
@@ -4176,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);
@@ -4274,6 +4328,7 @@
         // Default wifi configurations.
         sDefaults.putAll(Wifi.getDefaults());
         sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_FORWARDED_NUMBER_BOOL, false);
         sDefaults.putAll(Iwlan.getDefaults());
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 560c895..cf8fe6a 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -209,6 +209,19 @@
     }
 
     /**
+     * Get bands of the cell
+     *
+     * Reference: 3GPP TS 36.101 section 5.5
+     *
+     * @return List of band number or empty list if not available.
+     */
+    @NonNull
+    public List<Integer> getBands() {
+        // Todo: Add actual support
+        return Collections.emptyList();
+    }
+
+    /**
      * @return Cell bandwidth in kHz,
      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 40927a1..d4f181f 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -23,6 +23,7 @@
 import android.telephony.AccessNetworkConstants.NgranBands.NgranBand;
 import android.telephony.gsm.GsmCellLocation;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -42,7 +43,7 @@
     private final int mPci;
     private final int mTac;
     private final long mNci;
-    private final int mBand;
+    private final List<Integer> mBands;
 
     // a list of additional PLMN-IDs reported for this cell
     private final List<String> mAdditionalPlmns;
@@ -52,7 +53,7 @@
      * @param pci Physical Cell Id in range [0, 1007].
      * @param tac 16-bit Tracking Area Code.
      * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
-     * @param band Band number defined in 3GPP TS 38.101-1 and TS 38.101-2.
+     * @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2.
      * @param mccStr 3-digit Mobile Country Code in string format.
      * @param mncStr 2 or 3-digit Mobile Network Code in string format.
      * @param nci The 36-bit NR Cell Identity in range [0, 68719476735].
@@ -62,28 +63,28 @@
      *
      * @hide
      */
-    public CellIdentityNr(int pci, int tac, int nrArfcn, @NgranBand int band, String mccStr,
-            String mncStr, long nci, String alphal, String alphas, List<String> additionalPlmns) {
+    public CellIdentityNr(int pci, int tac, int nrArfcn, @NgranBand List<Integer> bands,
+                          String mccStr, String mncStr, long nci, String alphal, String alphas,
+                          List<String> additionalPlmns) {
         super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
         mPci = inRangeOrUnavailable(pci, 0, MAX_PCI);
         mTac = inRangeOrUnavailable(tac, 0, MAX_TAC);
         mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN);
-        mBand = inRangeOrUnavailable(band, AccessNetworkConstants.NgranBands.BAND_1,
-                AccessNetworkConstants.NgranBands.BAND_261);
+        mBands = new ArrayList<>(bands);
         mNci = inRangeOrUnavailable(nci, 0, MAX_NCI);
-        mAdditionalPlmns = additionalPlmns;
+        mAdditionalPlmns = new ArrayList<>(additionalPlmns);
     }
 
     /** @hide */
     public CellIdentityNr(android.hardware.radio.V1_4.CellIdentityNr cid) {
-        this(cid.pci, cid.tac, cid.nrarfcn, 0, cid.mcc, cid.mnc, cid.nci,
+        this(cid.pci, cid.tac, cid.nrarfcn, Collections.emptyList(), cid.mcc, cid.mnc, cid.nci,
                 cid.operatorNames.alphaLong, cid.operatorNames.alphaShort,
                 Collections.emptyList());
     }
 
     /** @hide */
     public CellIdentityNr(android.hardware.radio.V1_5.CellIdentityNr cid) {
-        this(cid.base.pci, cid.base.tac, cid.base.nrarfcn, cid.band, cid.base.mcc, cid.base.mnc,
+        this(cid.base.pci, cid.base.tac, cid.base.nrarfcn, cid.bands, cid.base.mcc, cid.base.mnc,
                 cid.base.nci, cid.base.operatorNames.alphaLong,
                 cid.base.operatorNames.alphaShort, cid.additionalPlmns);
     }
@@ -92,7 +93,7 @@
     @Override
     public @NonNull CellIdentityNr sanitizeLocationInfo() {
         return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mNrArfcn,
-                mBand, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort,
+                mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort,
                 mAdditionalPlmns);
     }
 
@@ -109,7 +110,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(super.hashCode(), mPci, mTac,
-                mNrArfcn, mBand, mNci, mAdditionalPlmns.hashCode());
+                mNrArfcn, mBands.hashCode(), mNci, mAdditionalPlmns.hashCode());
     }
 
     @Override
@@ -120,7 +121,7 @@
 
         CellIdentityNr o = (CellIdentityNr) other;
         return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn
-                && mBand == o.mBand && mNci == o.mNci
+                && mBands.equals(o.mBands) && mNci == o.mNci
                 && mAdditionalPlmns.equals(o.mAdditionalPlmns);
     }
 
@@ -148,16 +149,17 @@
     }
 
     /**
-     * Get band of the cell
+     * Get bands of the cell
      *
      * Reference: TS 38.101-1 table 5.2-1
      * Reference: TS 38.101-2 table 5.2-1
      *
-     * @return band number or {@link CellInfo@UNAVAILABLE} if not available.
+     * @return List of band number or empty list if not available.
      */
     @NgranBand
-    public int getBand() {
-        return mBand;
+    @NonNull
+    public List<Integer> getBands() {
+        return Collections.unmodifiableList(mBands);
     }
 
     /**
@@ -205,7 +207,7 @@
      */
     @NonNull
     public List<String> getAdditionalPlmns() {
-        return mAdditionalPlmns;
+        return Collections.unmodifiableList(mAdditionalPlmns);
     }
 
     @Override
@@ -214,7 +216,7 @@
                 .append(" mPci = ").append(mPci)
                 .append(" mTac = ").append(mTac)
                 .append(" mNrArfcn = ").append(mNrArfcn)
-                .append(" mBand = ").append(mBand)
+                .append(" mBands = ").append(mBands)
                 .append(" mMcc = ").append(mMccStr)
                 .append(" mMnc = ").append(mMncStr)
                 .append(" mNci = ").append(mNci)
@@ -231,7 +233,7 @@
         dest.writeInt(mPci);
         dest.writeInt(mTac);
         dest.writeInt(mNrArfcn);
-        dest.writeInt(mBand);
+        dest.writeList(mBands);
         dest.writeLong(mNci);
         dest.writeList(mAdditionalPlmns);
     }
@@ -242,7 +244,7 @@
         mPci = in.readInt();
         mTac = in.readInt();
         mNrArfcn = in.readInt();
-        mBand = in.readInt();
+        mBands = in.readArrayList(null);
         mNci = in.readLong();
         mAdditionalPlmns = in.readArrayList(null);
     }
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/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/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/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 9253f1c..86913a6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -99,7 +99,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;
@@ -2781,7 +2780,7 @@
     @UnsupportedAppUsage
     public boolean isNetworkRoaming(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
-        return getTelephonyProperty(subId, TelephonyProperties.operator_is_roaming(), false);
+        return getTelephonyProperty(phoneId, TelephonyProperties.operator_is_roaming(), false);
     }
 
     /**
@@ -5624,14 +5623,6 @@
                 .getTelephonyServiceManager().getTelephonyServiceRegisterer().get());
     }
 
-    private ITelephonyRegistry getTelephonyRegistry() {
-        return ITelephonyRegistry.Stub.asInterface(
-                TelephonyFrameworkInitializer
-                        .getTelephonyServiceManager()
-                        .getTelephonyRegistryServiceRegisterer()
-                        .get());
-    }
-
     private IOns getIOns() {
         return IOns.Stub.asInterface(
                 TelephonyFrameworkInitializer
@@ -5685,29 +5676,27 @@
      */
     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.");
+        boolean notifyNow = (getITelephony() != null);
+        TelephonyRegistryManager telephonyRegistry =
+                (TelephonyRegistryManager)
+                        mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (telephonyRegistry != 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;
             }
-        } catch (RemoteException ex) {
-            // system process dead
+            telephonyRegistry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
+                    listener, events, notifyNow);
+        } else {
+            Rlog.w(TAG, "telephony registry not ready.");
         }
     }
 
@@ -7359,6 +7348,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.
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index d5a48df..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.
@@ -246,13 +249,69 @@
      * Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
      * code.
      *
-     * <p>This code is an implementation detail of the embedded subscription manager and is only
-     * intended for logging or debugging purposes.
+     * <p>The value of this key is an integer and contains two portions. The first byte is
+     * OperationCode and the reaming three bytes is the ErrorCode.
+     *
+     * OperationCode is the first byte of the result code and is a categorization which defines what
+     * type of operation took place when an error occurred. e.g {@link #OPERATION_DOWNLOAD} means
+     * 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 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},
+     * 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},
+     * value will be an int.
+     */
+    public static final String EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE =
+            "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_ERROR_CODE";
+
+    /**
+     * 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";
+
+    /**
+     * 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";
+
+    /**
      * Key for an extra set on {@code #getDownloadableSubscriptionMetadata} PendingIntent result
      * callbacks providing the downloadable subscription metadata.
      */
@@ -491,6 +550,259 @@
     @SystemApi
     public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5;
 
+    /**
+     * List of OperationCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}'s
+     * value, an integer. @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"OPERATION_"}, value = {
+            OPERATION_SYSTEM,
+            OPERATION_SIM_SLOT,
+            OPERATION_EUICC_CARD,
+            OPERATION_SWITCH,
+            OPERATION_DOWNLOAD,
+            OPERATION_METADATA,
+            OPERATION_EUICC_GSMA,
+            OPERATION_APDU,
+            OPERATION_SMDX,
+            OPERATION_HTTP,
+            OPERATION_SMDX_SUBJECT_REASON_CODE,
+    })
+    public @interface OperationCode {
+    }
+
+    /**
+     * Internal system error.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_SYSTEM = 1;
+
+    /**
+     * SIM slot error. Failed to switch slot, failed to access the physical slot etc.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_SIM_SLOT = 2;
+
+    /**
+     * eUICC card error.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_EUICC_CARD = 3;
+
+    /**
+     * Generic switching profile error
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_SWITCH = 4;
+
+    /**
+     * Download profile error.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_DOWNLOAD = 5;
+
+    /**
+     * Subscription's metadata error
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_METADATA = 6;
+
+    /**
+     * eUICC returned an error defined in GSMA (SGP.22 v2.2) while running one of the ES10x
+     * functions.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_EUICC_GSMA = 7;
+
+    /**
+     * The exception of failing to execute an APDU command. It can be caused by an error
+     * happening on opening the basic or logical channel, or the response of the APDU command is
+     * not success (0x9000).
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_APDU = 8;
+
+    /**
+     * SMDX(SMDP/SMDS) error
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_SMDX = 9;
+
+    /**
+     * SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] error from GSMA (SGP.22 v2.2)
+     * When {@link #OPERATION_SMDX_SUBJECT_REASON_CODE} is used as the
+     * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}, the remaining three bytes of the integer
+     * result from {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} will be used to stored the
+     * SubjectCode and ReasonCode from the GSMA spec and NOT ErrorCode.
+     *
+     * The encoding will follow the format of:
+     * 1. The first byte of the result will be 255(0xFF).
+     * 2. Remaining three bytes(24 bits) will be split into six sections, 4 bits in each section.
+     * 3. A SubjectCode/ReasonCode will take 12 bits each.
+     * 4. The maximum number can be represented per section is 15, as that is the maximum number
+     * allowed to be stored into 4 bits
+     * 5. Maximum supported nested category from GSMA is three layers. E.g 8.11.1.2 is not
+     * supported.
+     *
+     * E.g given SubjectCode(8.11.1) and ReasonCode(5.1)
+     *
+     * Base10:  0       10      8       11      1       0       5       1
+     * Base2:   0000    1010    1000    1011    0001    0000    0101    0001
+     * Base16:  0       A       8       B       1       0       5       1
+     *
+     * Thus the integer stored in {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} is
+     * 0xA8B1051(176885841)
+     *
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_SMDX_SUBJECT_REASON_CODE = 10;
+
+    /**
+     * HTTP error
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int OPERATION_HTTP = 11;
+
+    /**
+     * List of ErrorCode corresponding to {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE}
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"ERROR_"}, value = {
+            ERROR_CARRIER_LOCKED,
+            ERROR_INVALID_ACTIVATION_CODE,
+            ERROR_INVALID_CONFIRMATION_CODE,
+            ERROR_INCOMPATIBLE_CARRIER,
+            ERROR_EUICC_INSUFFICIENT_MEMORY,
+            ERROR_TIME_OUT,
+            ERROR_EUICC_MISSING,
+            ERROR_UNSUPPORTED_VERSION,
+            ERROR_SIM_MISSING,
+            ERROR_INSTALL_PROFILE,
+            ERROR_DISALLOWED_BY_PPR,
+            ERROR_ADDRESS_MISSING,
+            ERROR_CERTIFICATE_ERROR,
+            ERROR_NO_PROFILES_AVAILABLE,
+            ERROR_CONNECTION_ERROR,
+            ERROR_INVALID_RESPONSE,
+            ERROR_OPERATION_BUSY,
+    })
+    public @interface ErrorCode{}
+
+    /**
+     * Operation such as downloading/switching to another profile failed due to device being
+     * carrier locked.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_CARRIER_LOCKED = 10000;
+
+    /**
+     * The activation code(SGP.22 v2.2 section[4.1]) is invalid.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_INVALID_ACTIVATION_CODE = 10001;
+
+    /**
+     * The confirmation code(SGP.22 v2.2 section[4.7]) is invalid.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_INVALID_CONFIRMATION_CODE = 10002;
+
+    /**
+     * The profile's carrier is incompatible with the LPA.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_INCOMPATIBLE_CARRIER = 10003;
+
+    /**
+     * There is no more space available on the eUICC for new profiles.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_EUICC_INSUFFICIENT_MEMORY = 10004;
+
+    /**
+     * Timed out while waiting for an operation to complete. i.e restart, disable,
+     * switch reset etc.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_TIME_OUT = 10005;
+
+    /**
+     * eUICC is missing or defective on the device.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_EUICC_MISSING = 10006;
+
+    /**
+     * The eUICC card(hardware) version is incompatible with the software
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_UNSUPPORTED_VERSION = 10007;
+
+    /**
+     * No SIM card is available in the device.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_SIM_MISSING = 10008;
+
+    /**
+     * 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_INSTALL_PROFILE = 10009;
+
+    /**
+     * Failed to load profile onto eUICC due to Profile Poicly Rules.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_DISALLOWED_BY_PPR = 10010;
+
+
+    /**
+     * Address is missing e.g SMDS/SMDP address is missing.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_ADDRESS_MISSING = 10011;
+
+    /**
+     * Certificate needed for authentication is not valid or missing. E.g  SMDP/SMDS authentication
+     * failed.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_CERTIFICATE_ERROR = 10012;
+
+
+    /**
+     * No profiles available.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_NO_PROFILES_AVAILABLE = 10013;
+
+    /**
+     * Failure to create a connection.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_CONNECTION_ERROR = 10014;
+
+    /**
+     * Response format is invalid. e.g SMDP/SMDS response contains invalid json, header or/and ASN1.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_INVALID_RESPONSE = 10015;
+
+    /**
+     * The operation is currently busy, try again later.
+     * @see {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} for details
+     */
+    public static final int ERROR_OPERATION_BUSY = 10016;
+
     private final Context mContext;
     private int mCardId;
 
@@ -939,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/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 8c9765b..9c1be48 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -328,6 +328,14 @@
     @Deprecated
     public static final String EXTRA_CALL_RAT_TYPE_ALT = "callRadioTech";
 
+    /**
+     * String extra property containing forwarded numbers associated with the current connection
+     * for an IMS call. The value is string array, and it can include multiple numbers, and
+     * the array values are expected E164 (e.g. +1 (650) 253-0000) format.
+     */
+    public static final String EXTRA_FORWARDED_NUMBER =
+            "android.telephony.ims.extra.FORWARDED_NUMBER";
+
     /** @hide */
     public int mServiceType;
     /** @hide */
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/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..7216776 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";
 
@@ -169,6 +174,7 @@
      * Provides a one-time callback for the response to a UCE request. After this callback is called
      * by the framework, the reference to this callback will be discarded on the service side.
      * @see #requestCapabilities(Executor, List, CapabilitiesCallback)
+     * @hide
      */
     public static class CapabilitiesCallback {
 
@@ -196,6 +202,7 @@
     /**
      * Not to be instantiated directly, use
      * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
+     * @hide
      */
     RcsUceAdapter(int subId) {
         mSubId = subId;
@@ -219,6 +226,7 @@
      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
      * available. This can happen if the ImsService has crashed, for example, or if the subscription
      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
+     * @hide
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void requestCapabilities(@CallbackExecutor Executor executor,
@@ -281,6 +289,7 @@
      * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
      * available. This can happen if the ImsService has crashed, for example, or if the subscription
      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
+     * @hide
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public @PublishState int getUcePublishState() throws ImsException {
@@ -305,7 +314,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..f3aea49 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -325,7 +325,6 @@
         */
         @NonNull
         @Override
-        @SystemApi @TestApi
         public String toString() {
             StringBuilder builder = new StringBuilder("MmTel Capabilities - [");
             builder.append("Voice: ");
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index 3ec4f34..f13371c 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -17,6 +17,8 @@
 package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.Bundle;
@@ -206,6 +208,13 @@
             return ImsUtImplBase.this.updateCallBarringForServiceClass(
                     cbType, action, barrList, serviceClass);
         }
+
+        @Override
+        public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
+                int serviceClass, String password) throws RemoteException {
+            return ImsUtImplBase.this.updateCallBarringWithPassword(
+                    cbType, action, barrList, serviceClass, password);
+        }
     };
 
     /**
@@ -328,6 +337,14 @@
     }
 
     /**
+     * Updates the configuration of the call barring for specified service class with password.
+     */
+    public int updateCallBarringWithPassword(int cbType, int action, @Nullable String[] barrList,
+            int serviceClass, @NonNull String password) {
+        return -1;
+    }
+
+    /**
      * Updates the configuration of the call forward.
      */
     public int updateCallForward(int action, int condition, String number, int serviceClass,
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index 15f8371..4a5380e 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -166,6 +166,12 @@
             String[] barrList, int serviceClass);
 
     /**
+     * Modifies the configuration of the call barring for specified service class with password.
+     */
+    public void updateCallBarring(int cbType, int action, Message result,
+            String[] barrList, int serviceClass, String password);
+
+    /**
      * Modifies the configuration of the call forward.
      */
     public void updateCallForward(int action, int condition, String number,
diff --git a/telephony/java/com/android/ims/internal/IImsUt.aidl b/telephony/java/com/android/ims/internal/IImsUt.aidl
index 4f97cc5..302be65 100644
--- a/telephony/java/com/android/ims/internal/IImsUt.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUt.aidl
@@ -122,4 +122,10 @@
      */
     int updateCallBarringForServiceClass(int cbType, int action, in String[] barrList,
             int serviceClass);
+
+    /**
+     * Updates the configuration of the call barring for specified service class with password.
+     */
+    int updateCallBarringWithPassword(int cbType, int action, in String[] barrList,
+            int serviceClass, String password);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6aa5a52..3f573c9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -831,6 +831,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.
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/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/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index cc260ac..32ca250 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -2,7 +2,6 @@
 package android.test.mock {
 
   public class MockContext extends android.content.Context {
-    method public android.view.Display getDisplay();
     method public int getDisplayId();
   }
 
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 9d913b9..36074ed 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -17,6 +17,7 @@
 package android.test.mock;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
@@ -811,6 +812,11 @@
     }
 
     @Override
+    public @NonNull Context createWindowContext(int type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean isRestricted() {
         throw new UnsupportedOperationException();
     }
@@ -821,7 +827,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @hide */
     @Override
     public Display getDisplay() {
         throw new UnsupportedOperationException();
diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp
index e7a63e4..78850c5 100644
--- a/tests/ApkVerityTest/block_device_writer/Android.bp
+++ b/tests/ApkVerityTest/block_device_writer/Android.bp
@@ -30,7 +30,23 @@
         "-g",
     ],
     shared_libs: ["libbase", "libutils"],
+    // For some reasons, cuttlefish (x86) uses x86_64 test suites for testing. Unfortunately, when
+    // the uploader does not pick up the executable from correct output location. The following
+    // workaround allows the test to:
+    //  * upload the 32-bit exectuable for both 32 and 64 bits devices to use
+    //  * refer to the same executable name in Java
+    //  * no need to force the Java test to be archiecture specific.
+    //
+    // See b/145573317 for details.
+    multilib: {
+        lib32: {
+            suffix: "",
+        },
+        lib64: {
+            suffix: "64",  // not really used
+        },
+    },
 
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "pts"],
     gtest: false,
 }
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/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
index 65a3d8a..c900eae 100644
--- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/SoundTriggerTest.java
@@ -30,6 +30,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Random;
 import java.util.UUID;
 
@@ -38,7 +39,8 @@
 
     @SmallTest
     public void testKeyphraseParcelUnparcel_noUsers() throws Exception {
-        Keyphrase keyphrase = new Keyphrase(1, 0, "en-US", "hello", null);
+        Keyphrase keyphrase = new Keyphrase(1, 0,
+                Locale.forLanguageTag("en-US"), "hello", null);
 
         // Write to a parcel
         Parcel parcel = Parcel.obtain();
@@ -57,7 +59,8 @@
 
     @SmallTest
     public void testKeyphraseParcelUnparcel_zeroUsers() throws Exception {
-        Keyphrase keyphrase = new Keyphrase(1, 0, "en-US", "hello", new int[0]);
+        Keyphrase keyphrase = new Keyphrase(1, 0,
+                Locale.forLanguageTag("en-US"), "hello", new int[0]);
 
         // Write to a parcel
         Parcel parcel = Parcel.obtain();
@@ -76,7 +79,8 @@
 
     @SmallTest
     public void testKeyphraseParcelUnparcel_pos() throws Exception {
-        Keyphrase keyphrase = new Keyphrase(1, 0, "en-US", "hello", new int[] {1, 2, 3, 4, 5});
+        Keyphrase keyphrase = new Keyphrase(1, 0,
+                Locale.forLanguageTag("en-US"), "hello", new int[] {1, 2, 3, 4, 5});
 
         // Write to a parcel
         Parcel parcel = Parcel.obtain();
@@ -96,8 +100,10 @@
     @SmallTest
     public void testKeyphraseSoundModelParcelUnparcel_noData() throws Exception {
         Keyphrase[] keyphrases = new Keyphrase[2];
-        keyphrases[0] = new Keyphrase(1, 0, "en-US", "hello", new int[] {0});
-        keyphrases[1] = new Keyphrase(2, 0, "fr-FR", "there", new int[] {1, 2});
+        keyphrases[0] = new Keyphrase(1, 0, Locale.forLanguageTag("en-US"),
+                "hello", new int[] {0});
+        keyphrases[1] = new Keyphrase(2, 0, Locale.forLanguageTag("fr-FR"),
+                "there", new int[] {1, 2});
         KeyphraseSoundModel ksm = new KeyphraseSoundModel(UUID.randomUUID(), UUID.randomUUID(),
                 null, keyphrases);
 
@@ -119,8 +125,10 @@
     @SmallTest
     public void testKeyphraseSoundModelParcelUnparcel_zeroData() throws Exception {
         Keyphrase[] keyphrases = new Keyphrase[2];
-        keyphrases[0] = new Keyphrase(1, 0, "en-US", "hello", new int[] {0});
-        keyphrases[1] = new Keyphrase(2, 0, "fr-FR", "there", new int[] {1, 2});
+        keyphrases[0] = new Keyphrase(1, 0, Locale.forLanguageTag("en-US"),
+                "hello", new int[] {0});
+        keyphrases[1] = new Keyphrase(2, 0, Locale.forLanguageTag("fr-FR"),
+                "there", new int[] {1, 2});
         KeyphraseSoundModel ksm = new KeyphraseSoundModel(UUID.randomUUID(), UUID.randomUUID(),
                 new byte[0], keyphrases);
 
@@ -186,8 +194,10 @@
     @LargeTest
     public void testKeyphraseSoundModelParcelUnparcel_largeData() throws Exception {
         Keyphrase[] keyphrases = new Keyphrase[2];
-        keyphrases[0] = new Keyphrase(1, 0, "en-US", "hello", new int[] {0});
-        keyphrases[1] = new Keyphrase(2, 0, "fr-FR", "there", new int[] {1, 2});
+        keyphrases[0] = new Keyphrase(1, 0, Locale.forLanguageTag("en-US"),
+                "hello", new int[] {0});
+        keyphrases[1] = new Keyphrase(2, 0, Locale.forLanguageTag("fr-FR"),
+                "there", new int[] {1, 2});
         byte[] data = new byte[200 * 1024];
         mRandom.nextBytes(data);
         KeyphraseSoundModel ksm = new KeyphraseSoundModel(UUID.randomUUID(), UUID.randomUUID(),
diff --git a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
index 6687f83..6169671 100644
--- a/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
+++ b/tests/SurfaceControlViewHostTest/src/com/android/test/viewembed/SurfaceControlViewHostTest.java
@@ -46,15 +46,15 @@
 
         mView.setZOrderOnTop(true);
         mView.getHolder().addCallback(this);
+
+        addEmbeddedView();
     }
 
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
+    void addEmbeddedView() {
         mVr = new SurfaceControlViewHost(this, this.getDisplay(),
-                mView.getInputToken());
+                mView.getHostToken());
 
-        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-        t.reparent(mVr.getSurfacePackage().getSurfaceControl(), mView.getSurfaceControl()).apply();
+        mView.setChildSurfacePackage(mVr.getSurfacePackage());
 
         Button v = new Button(this);
         v.setBackgroundColor(Color.BLUE);
@@ -70,6 +70,10 @@
     }
 
     @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
         Canvas canvas = holder.lockCanvas();
         canvas.drawColor(Color.GREEN);
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index 54c944f9..b357ad0 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -16,9 +16,6 @@
 
 package com.android.test.voiceenrollment;
 
-import java.util.Random;
-import java.util.UUID;
-
 import android.app.Activity;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
@@ -29,6 +26,13 @@
 import android.view.View;
 import android.widget.Toast;
 
+import java.util.Locale;
+import java.util.Random;
+import java.util.UUID;
+
+/**
+ * TODO: must be transitioned to a service.
+ */
 public class TestEnrollmentActivity extends Activity {
     private static final String TAG = "TestEnrollmentActivity";
     private static final boolean DBG = false;
@@ -56,7 +60,8 @@
      * Performs a fresh enrollment.
      */
     public void onEnrollButtonClicked(View v) {
-        Keyphrase kp = new Keyphrase(KEYPHRASE_ID, RECOGNITION_MODES, BCP47_LOCALE, TEXT,
+        Keyphrase kp = new Keyphrase(KEYPHRASE_ID, RECOGNITION_MODES,
+                Locale.forLanguageTag(BCP47_LOCALE), TEXT,
                 new int[] { UserManager.get(this).getUserHandle() /* current user */});
         UUID modelUuid = UUID.randomUUID();
         // Generate a fake model to push.
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
index f3c89d8a..01e212d 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
@@ -22,6 +22,7 @@
 import android.app.Activity;
 import android.graphics.Insets;
 import android.os.Bundle;
+import android.util.Log;
 import android.util.Property;
 import android.view.View;
 import android.view.WindowInsets;
@@ -67,8 +68,8 @@
         }
     };
 
-    float showY;
-    float hideY;
+    float startY;
+    float endY;
     InsetsAnimation imeAnim;
 
     @Override
@@ -84,16 +85,6 @@
                 v.getWindowInsetsController().hide(Type.ime());
             }
         });
-        mRoot.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
-            if (imeAnim == null) {
-                return;
-            }
-            if (mRoot.getRootWindowInsets().isVisible(Type.ime())) {
-                showY = mButton.getTop();
-            } else {
-                hideY = mButton.getTop();
-            }
-        });
         mRoot.setWindowInsetsAnimationCallback(new WindowInsetsAnimationCallback() {
 
             @Override
@@ -106,22 +97,19 @@
                 if ((animation.getTypeMask() & Type.ime()) != 0) {
                     imeAnim = animation;
                 }
-                if (mRoot.getRootWindowInsets().isVisible(Type.ime())) {
-                    showY = mButton.getTop();
-                } else {
-                    hideY = mButton.getTop();
-                }
+                startY = mButton.getTop();
             }
 
             @Override
             public WindowInsets onProgress(WindowInsets insets) {
-                mButton.setY(hideY + (showY - hideY) * imeAnim.getInterpolatedFraction());
+                mButton.setY(startY + (endY - startY) * imeAnim.getInterpolatedFraction());
                 return insets;
             }
 
             @Override
             public AnimationBounds onStart(InsetsAnimation animation,
                     AnimationBounds bounds) {
+                endY = mButton.getTop();
                 return bounds;
             }
 
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
new file mode 100644
index 0000000..7ab4b56
--- /dev/null
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -0,0 +1,248 @@
+/*
+ * 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 static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
+import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
+
+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.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 {
+    private static final int NET_ID = 1;
+    private static final int DETECTION_METHOD = 2;
+    private static final long TIMESTAMP = 10L;
+    private static final String INTERFACE_NAME = "interface";
+    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);
+
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+        networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(BUNDLE_KEY, BUNDLE_VALUE);
+
+        return new ConnectivityReport(
+                new Network(NET_ID), TIMESTAMP, linkProperties, networkCapabilities, bundle);
+    }
+
+    private ConnectivityReport createDefaultConnectivityReport() {
+        return new ConnectivityReport(
+                new Network(0),
+                0L,
+                new LinkProperties(),
+                new NetworkCapabilities(),
+                PersistableBundle.EMPTY);
+    }
+
+    @Test
+    public void testPersistableBundleEquals() {
+        assertFalse(
+                ConnectivityDiagnosticsManager.persistableBundleEquals(
+                        null, PersistableBundle.EMPTY));
+        assertFalse(
+                ConnectivityDiagnosticsManager.persistableBundleEquals(
+                        PersistableBundle.EMPTY, null));
+        assertTrue(
+                ConnectivityDiagnosticsManager.persistableBundleEquals(
+                        PersistableBundle.EMPTY, PersistableBundle.EMPTY));
+
+        final PersistableBundle a = new PersistableBundle();
+        a.putString(BUNDLE_KEY, BUNDLE_VALUE);
+
+        final PersistableBundle b = new PersistableBundle();
+        b.putString(BUNDLE_KEY, BUNDLE_VALUE);
+
+        final PersistableBundle c = new PersistableBundle();
+        c.putString(BUNDLE_KEY, null);
+
+        assertFalse(
+                ConnectivityDiagnosticsManager.persistableBundleEquals(PersistableBundle.EMPTY, a));
+        assertFalse(
+                ConnectivityDiagnosticsManager.persistableBundleEquals(a, PersistableBundle.EMPTY));
+
+        assertTrue(ConnectivityDiagnosticsManager.persistableBundleEquals(a, b));
+        assertTrue(ConnectivityDiagnosticsManager.persistableBundleEquals(b, a));
+
+        assertFalse(ConnectivityDiagnosticsManager.persistableBundleEquals(a, c));
+        assertFalse(ConnectivityDiagnosticsManager.persistableBundleEquals(c, a));
+    }
+
+    @Test
+    public void testConnectivityReportEquals() {
+        assertEquals(createSampleConnectivityReport(), createSampleConnectivityReport());
+        assertEquals(createDefaultConnectivityReport(), createDefaultConnectivityReport());
+
+        final LinkProperties linkProperties = new LinkProperties();
+        linkProperties.setInterfaceName(INTERFACE_NAME);
+
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+        networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(BUNDLE_KEY, BUNDLE_VALUE);
+
+        assertNotEquals(
+                createDefaultConnectivityReport(),
+                new ConnectivityReport(
+                        new Network(NET_ID),
+                        0L,
+                        new LinkProperties(),
+                        new NetworkCapabilities(),
+                        PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultConnectivityReport(),
+                new ConnectivityReport(
+                        new Network(0),
+                        TIMESTAMP,
+                        new LinkProperties(),
+                        new NetworkCapabilities(),
+                        PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultConnectivityReport(),
+                new ConnectivityReport(
+                        new Network(0),
+                        0L,
+                        linkProperties,
+                        new NetworkCapabilities(),
+                        PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultConnectivityReport(),
+                new ConnectivityReport(
+                        new Network(0),
+                        TIMESTAMP,
+                        new LinkProperties(),
+                        networkCapabilities,
+                        PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultConnectivityReport(),
+                new ConnectivityReport(
+                        new Network(0),
+                        TIMESTAMP,
+                        new LinkProperties(),
+                        new NetworkCapabilities(),
+                        bundle));
+    }
+
+    @Test
+    public void testConnectivityReportParcelUnparcel() {
+        assertParcelSane(createSampleConnectivityReport(), 5);
+    }
+
+    private DataStallReport createSampleDataStallReport() {
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(BUNDLE_KEY, BUNDLE_VALUE);
+        return new DataStallReport(new Network(NET_ID), TIMESTAMP, DETECTION_METHOD, bundle);
+    }
+
+    private DataStallReport createDefaultDataStallReport() {
+        return new DataStallReport(new Network(0), 0L, 0, PersistableBundle.EMPTY);
+    }
+
+    @Test
+    public void testDataStallReportEquals() {
+        assertEquals(createSampleDataStallReport(), createSampleDataStallReport());
+        assertEquals(createDefaultDataStallReport(), createDefaultDataStallReport());
+
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putString(BUNDLE_KEY, BUNDLE_VALUE);
+
+        assertNotEquals(
+                createDefaultDataStallReport(),
+                new DataStallReport(new Network(NET_ID), 0L, 0, PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultDataStallReport(),
+                new DataStallReport(new Network(0), TIMESTAMP, 0, PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultDataStallReport(),
+                new DataStallReport(new Network(0), 0L, DETECTION_METHOD, PersistableBundle.EMPTY));
+        assertNotEquals(
+                createDefaultDataStallReport(), new DataStallReport(new Network(0), 0L, 0, bundle));
+    }
+
+    @Test
+    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/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 d13a625..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);
 
@@ -88,15 +89,19 @@
 
     boolean disableNetwork(int netId, String packageName);
 
+    void allowAutojoinGlobal(boolean choice);
+
     void allowAutojoin(int netId, boolean choice);
 
     void allowAutojoinPasspoint(String fqdn, boolean enableAutoJoin);
 
     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);
 
@@ -179,8 +184,6 @@
 
     int getVerboseLoggingLevel();
 
-    void enableWifiConnectivityManager(boolean enabled);
-
     void disableEphemeralNetwork(String SSID, String packageName);
 
     void factoryReset(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/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index f6e3ff0..fb3e794 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
@@ -4299,6 +4278,23 @@
     }
 
     /**
+     * Allows the OEM to enable/disable auto-join globally.
+     *
+     * @param choice true to allow autojoin, false to disallow autojoin
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void allowAutojoinGlobal(boolean choice) {
+        try {
+            mService.allowAutojoinGlobal(choice);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
      * Sets the user choice for allowing auto-join to a network.
      * The updated choice will be made available through the updated config supplied by the
      * CONFIGURED_NETWORKS_CHANGED broadcast.
@@ -4353,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.
@@ -4925,18 +4940,6 @@
     }
 
     /**
-     * Enable/disable WifiConnectivityManager
-     * @hide
-     */
-    public void enableWifiConnectivityManager(boolean enabled) {
-        try {
-            mService.enableWifiConnectivityManager(enabled);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Returns a byte stream representing the data that needs to be backed up to save the
      * current Wifi state.
      * This Wifi state can be restored by calling {@link #restoreBackupData(byte[])}.
@@ -5144,18 +5147,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
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 19d09d1..b467553 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -178,6 +178,11 @@
     }
 
     @Override
+    public void allowAutojoinGlobal(boolean choice) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public void allowAutojoin(int netId, boolean choice) {
         throw new UnsupportedOperationException();
     }
@@ -193,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();
     }
@@ -404,7 +414,8 @@
         throw new UnsupportedOperationException();
     }
 
-    @Override
+    /** @deprecated use {@link #allowAutojoinGlobal(boolean)} instead */
+    @Deprecated
     public void enableWifiConnectivityManager(boolean enabled) {
         throw new UnsupportedOperationException();
     }
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);
     }
 
     /**