Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 17033e0..c15b641 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -10,6 +10,7 @@
         "androidx.test.ext.junit",
         "androidx.annotation_annotation",
         "apct-perftests-utils",
+        "collector-device-lib-platform",
     ],
 
     libs: ["android.test.base"],
@@ -18,4 +19,8 @@
 
     test_suites: ["device-tests"],
 
+    data: [":perfetto_artifacts"],
+
+    certificate: "platform",
+
 }
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index c112d87..4903510 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -15,74 +15,122 @@
   ~ limitations under the License.
   -->
 <configuration description="Runs PackageManagerPerfTests metric instrumentation.">
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="apct-metric-instrumentation" />
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-suite-tag" value="apct-metric-instrumentation"/>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="PackageManagerPerfTests.apk" />
+        <option name="cleanup-apks" value="true"/>
+        <option name="test-file-name" value="PackageManagerPerfTests.apk"/>
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="force-queryable" value="false" />
-        <option name="test-file-name" value="QueriesAll0.apk" />
-        <option name="test-file-name" value="QueriesAll1.apk" />
-        <option name="test-file-name" value="QueriesAll2.apk" />
-        <option name="test-file-name" value="QueriesAll3.apk" />
-        <option name="test-file-name" value="QueriesAll4.apk" />
-        <option name="test-file-name" value="QueriesAll5.apk" />
-        <option name="test-file-name" value="QueriesAll6.apk" />
-        <option name="test-file-name" value="QueriesAll7.apk" />
-        <option name="test-file-name" value="QueriesAll8.apk" />
-        <option name="test-file-name" value="QueriesAll9.apk" />
-        <option name="test-file-name" value="QueriesAll10.apk" />
-        <option name="test-file-name" value="QueriesAll11.apk" />
-        <option name="test-file-name" value="QueriesAll12.apk" />
-        <option name="test-file-name" value="QueriesAll13.apk" />
-        <option name="test-file-name" value="QueriesAll14.apk" />
-        <option name="test-file-name" value="QueriesAll15.apk" />
-        <option name="test-file-name" value="QueriesAll16.apk" />
-        <option name="test-file-name" value="QueriesAll17.apk" />
-        <option name="test-file-name" value="QueriesAll18.apk" />
-        <option name="test-file-name" value="QueriesAll19.apk" />
-        <option name="test-file-name" value="QueriesAll20.apk" />
-        <option name="test-file-name" value="QueriesAll21.apk" />
-        <option name="test-file-name" value="QueriesAll22.apk" />
-        <option name="test-file-name" value="QueriesAll23.apk" />
-        <option name="test-file-name" value="QueriesAll24.apk" />
-        <option name="test-file-name" value="QueriesAll25.apk" />
-        <option name="test-file-name" value="QueriesAll26.apk" />
-        <option name="test-file-name" value="QueriesAll27.apk" />
-        <option name="test-file-name" value="QueriesAll28.apk" />
-        <option name="test-file-name" value="QueriesAll29.apk" />
-        <option name="test-file-name" value="QueriesAll30.apk" />
-        <option name="test-file-name" value="QueriesAll31.apk" />
-        <option name="test-file-name" value="QueriesAll32.apk" />
-        <option name="test-file-name" value="QueriesAll33.apk" />
-        <option name="test-file-name" value="QueriesAll34.apk" />
-        <option name="test-file-name" value="QueriesAll35.apk" />
-        <option name="test-file-name" value="QueriesAll36.apk" />
-        <option name="test-file-name" value="QueriesAll37.apk" />
-        <option name="test-file-name" value="QueriesAll38.apk" />
-        <option name="test-file-name" value="QueriesAll39.apk" />
-        <option name="test-file-name" value="QueriesAll40.apk" />
-        <option name="test-file-name" value="QueriesAll41.apk" />
-        <option name="test-file-name" value="QueriesAll42.apk" />
-        <option name="test-file-name" value="QueriesAll43.apk" />
-        <option name="test-file-name" value="QueriesAll44.apk" />
-        <option name="test-file-name" value="QueriesAll45.apk" />
-        <option name="test-file-name" value="QueriesAll46.apk" />
-        <option name="test-file-name" value="QueriesAll47.apk" />
-        <option name="test-file-name" value="QueriesAll48.apk" />
-        <option name="test-file-name" value="QueriesAll49.apk" />
+        <option name="cleanup-apks" value="true"/>
+        <option name="force-queryable" value="false"/>
+        <option name="test-file-name" value="QueriesAll0.apk"/>
+        <option name="test-file-name" value="QueriesAll1.apk"/>
+        <option name="test-file-name" value="QueriesAll2.apk"/>
+        <option name="test-file-name" value="QueriesAll3.apk"/>
+        <option name="test-file-name" value="QueriesAll4.apk"/>
+        <option name="test-file-name" value="QueriesAll5.apk"/>
+        <option name="test-file-name" value="QueriesAll6.apk"/>
+        <option name="test-file-name" value="QueriesAll7.apk"/>
+        <option name="test-file-name" value="QueriesAll8.apk"/>
+        <option name="test-file-name" value="QueriesAll9.apk"/>
+        <option name="test-file-name" value="QueriesAll10.apk"/>
+        <option name="test-file-name" value="QueriesAll11.apk"/>
+        <option name="test-file-name" value="QueriesAll12.apk"/>
+        <option name="test-file-name" value="QueriesAll13.apk"/>
+        <option name="test-file-name" value="QueriesAll14.apk"/>
+        <option name="test-file-name" value="QueriesAll15.apk"/>
+        <option name="test-file-name" value="QueriesAll16.apk"/>
+        <option name="test-file-name" value="QueriesAll17.apk"/>
+        <option name="test-file-name" value="QueriesAll18.apk"/>
+        <option name="test-file-name" value="QueriesAll19.apk"/>
+        <option name="test-file-name" value="QueriesAll20.apk"/>
+        <option name="test-file-name" value="QueriesAll21.apk"/>
+        <option name="test-file-name" value="QueriesAll22.apk"/>
+        <option name="test-file-name" value="QueriesAll23.apk"/>
+        <option name="test-file-name" value="QueriesAll24.apk"/>
+        <option name="test-file-name" value="QueriesAll25.apk"/>
+        <option name="test-file-name" value="QueriesAll26.apk"/>
+        <option name="test-file-name" value="QueriesAll27.apk"/>
+        <option name="test-file-name" value="QueriesAll28.apk"/>
+        <option name="test-file-name" value="QueriesAll29.apk"/>
+        <option name="test-file-name" value="QueriesAll30.apk"/>
+        <option name="test-file-name" value="QueriesAll31.apk"/>
+        <option name="test-file-name" value="QueriesAll32.apk"/>
+        <option name="test-file-name" value="QueriesAll33.apk"/>
+        <option name="test-file-name" value="QueriesAll34.apk"/>
+        <option name="test-file-name" value="QueriesAll35.apk"/>
+        <option name="test-file-name" value="QueriesAll36.apk"/>
+        <option name="test-file-name" value="QueriesAll37.apk"/>
+        <option name="test-file-name" value="QueriesAll38.apk"/>
+        <option name="test-file-name" value="QueriesAll39.apk"/>
+        <option name="test-file-name" value="QueriesAll40.apk"/>
+        <option name="test-file-name" value="QueriesAll41.apk"/>
+        <option name="test-file-name" value="QueriesAll42.apk"/>
+        <option name="test-file-name" value="QueriesAll43.apk"/>
+        <option name="test-file-name" value="QueriesAll44.apk"/>
+        <option name="test-file-name" value="QueriesAll45.apk"/>
+        <option name="test-file-name" value="QueriesAll46.apk"/>
+        <option name="test-file-name" value="QueriesAll47.apk"/>
+        <option name="test-file-name" value="QueriesAll48.apk"/>
+        <option name="test-file-name" value="QueriesAll49.apk"/>
     </target_preparer>
 
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.perftests.packagemanager" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.perftests.packagemanager"/>
         <option name="hidden-api-checks" value="false"/>
     </test>
 
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
-        <option name="directory-keys" value="/data/local/PackageManagerPerfTests" />
-        <option name="collect-on-run-ended-only" value="true" />
+        <option name="directory-keys" value="/data/local/PackageManagerPerfTests"/>
+        <option name="collect-on-run-ended-only" value="true"/>
     </metrics_collector>
+
+    <!-- Needed for pushing the trace config file -->
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="push-file" key="trace_config_detailed.textproto"
+                value="/data/misc/perfetto-traces/trace_config.textproto"/>
+        <!--Install the content provider automatically when we push some file in sdcard folder.-->
+        <!--Needed to avoid the installation during the test suite.-->
+        <option name="push-file" key="trace_config_detailed.textproto"
+                value="/sdcard/sample.textproto"/>
+    </target_preparer>
+
+    <!-- Needed for pulling the collected trace config on to the host -->
+    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+        <option name="pull-pattern-keys" value="perfetto_file_path"/>
+    </metrics_collector>
+
+    <!-- Needed for storing the perfetto trace files in the sdcard/test_results -->
+    <option name="isolated-storage" value="false"/>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.perftests.packagemanager"/>
+        <option name="hidden-api-checks" value="false"/>
+
+        <!-- Listener related args for collecting the traces and waiting for the device to
+             stabilize. -->
+        <option name="device-listeners"
+                value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener"/>
+        <!-- Guarantee that user defined RunListeners will be running before any of the default
+             listeners defined in this runner. -->
+        <option name="instrumentation-arg" key="newRunListenerMode" value="true"/>
+
+        <!-- ProcLoadListener related arguments -->
+        <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting
+             the test run -->
+        <option name="instrumentation-arg" key="procload-collector:per_run" value="true"/>
+        <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3"/>
+        <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000"/>
+        <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000"/>
+
+        <!-- PerfettoListener related arguments -->
+        <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/>
+        <option name="instrumentation-arg" key="perfetto_config_file"
+                value="trace_config.textproto"/>
+
+    </test>
+
+
 </configuration>
diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS
index ce0c212..1703369 100644
--- a/apex/appsearch/OWNERS
+++ b/apex/appsearch/OWNERS
@@ -1 +1,3 @@
+adorokhine@google.com
 sudheersai@google.com
+yamasani@google.com
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 380c646..ae9e7ff 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -7,6 +7,20 @@
     method public boolean isSuccess();
   }
 
+  public class AppSearchManager {
+    method public void createSearchSession(@NonNull android.app.appsearch.AppSearchManager.SearchContext, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.AppSearchSession>>);
+  }
+
+  public static final class AppSearchManager.SearchContext {
+    method @NonNull public String getDatabaseName();
+  }
+
+  public static final class AppSearchManager.SearchContext.Builder {
+    ctor public AppSearchManager.SearchContext.Builder();
+    method @NonNull public android.app.appsearch.AppSearchManager.SearchContext build();
+    method @NonNull public android.app.appsearch.AppSearchManager.SearchContext.Builder setDatabaseName(@NonNull String);
+  }
+
   public final class AppSearchResult<ValueType> {
     method @Nullable public String getErrorMessage();
     method public int getResultCode();
@@ -66,6 +80,21 @@
     method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int);
   }
 
+  public final class AppSearchSession {
+    method public void getByUri(@NonNull android.app.appsearch.GetByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
+    method public void getSchema(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.Set<android.app.appsearch.AppSearchSchema>>>);
+    method public void putDocuments(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
+    method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+    method public void removeByQuery(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
+    method public void removeByUri(@NonNull android.app.appsearch.RemoveByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
+    method public void setSchema(@NonNull android.app.appsearch.SetSchemaRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
+  }
+
+  public interface BatchResultCallback<KeyType, ValueType> {
+    method public void onResult(@NonNull android.app.appsearch.AppSearchBatchResult<KeyType,ValueType>);
+    method public default void onSystemError(@Nullable Throwable);
+  }
+
   public class GenericDocument {
     ctor protected GenericDocument(@NonNull android.app.appsearch.GenericDocument);
     method public long getCreationTimestampMillis();
@@ -162,6 +191,11 @@
     method public int getStart();
   }
 
+  public class SearchResults implements java.io.Closeable {
+    method public void close();
+    method public void getNextPage(@NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.List<android.app.appsearch.SearchResult>>>);
+  }
+
   public final class SearchSpec {
     method public int getMaxSnippetSize();
     method @NonNull public java.util.List<java.lang.String> getNamespaces();
diff --git a/apex/appsearch/framework/api/system-current.txt b/apex/appsearch/framework/api/system-current.txt
index 4a6194e..73a4a19 100644
--- a/apex/appsearch/framework/api/system-current.txt
+++ b/apex/appsearch/framework/api/system-current.txt
@@ -1,9 +1,17 @@
 // Signature format: 2.0
 package android.app.appsearch {
 
+  public class AppSearchManager {
+    method public void createGlobalSearchSession(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.GlobalSearchSession>>);
+  }
+
   public class AppSearchManagerFrameworkInitializer {
     method public static void initialize();
   }
 
+  public class GlobalSearchSession {
+    method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+  }
+
 }
 
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 442ca7b..c82119d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
@@ -39,8 +40,6 @@
  *
  * <p>Apps can index structured text documents with AppSearch, which can then be retrieved through
  * the query API.
- *
- * @hide
  */
 // TODO(b/148046169): This class header needs a detailed example/tutorial.
 @SystemService(Context.APP_SEARCH_SERVICE)
@@ -92,7 +91,8 @@
              *
              * <p>Database name cannot contain {@code '/'}.
              *
-             * <p>If not specified, defaults to {@link #DEFAULT_DATABASE_NAME}.
+             * <p>If not specified, defaults to the empty string.
+             *
              * @param databaseName The name of the database.
              * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
              */
@@ -150,7 +150,9 @@
      * @param callback      The {@link AppSearchResult}&lt;{@link GlobalSearchSession}&gt; of
      *                      performing this operation. Or a {@link AppSearchResult} with failure
      *                      reason code and error information.
+     * @hide
      */
+    @SystemApi
     public void createGlobalSearchSession(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
@@ -300,6 +302,7 @@
      * @throws RuntimeException If an error occurred during the execution.
      *
      * @deprecated use {@link AppSearchSession#getByUri} instead.
+     * @hide
      */
     public AppSearchBatchResult<String, GenericDocument> getByUri(
             @NonNull GetByUriRequest request) {
@@ -443,6 +446,7 @@
      * @throws RuntimeException If an error occurred during the execution.
      *
      * @deprecated use {@link AppSearchSession#removeByUri} instead.
+     * @hide
      */
     public AppSearchBatchResult<String, Void> removeByUri(@NonNull RemoveByUriRequest request) {
         List<String> uris = new ArrayList<>(request.getUris());
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index b7cd4f5..3e813ea 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -18,10 +18,10 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
-import android.app.appsearch.exceptions.AppSearchException;
 import android.os.Bundle;
 import android.os.ParcelableException;
 import android.os.RemoteException;
+import android.util.ArraySet;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -34,7 +34,8 @@
 /**
  * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
  * placed and queried.
- * @hide
+ *
+ * This class is thread safe.
  */
 public final class AppSearchSession {
     private final String mDatabaseName;
@@ -79,7 +80,7 @@
     }
 
     /**
-     * Sets the schema will be used by documents provided to the {@link #putDocuments} method.
+     * Sets the schema that will be used by documents provided to the {@link #putDocuments} method.
      *
      * <p>The schema provided here is compared to the stored copy of the schema previously supplied
      * to {@link #setSchema}, if any, to determine how to treat existing documents. The following
@@ -123,11 +124,19 @@
      * <p>It is a no-op to set the same schema as has been previously set; this is handled
      * efficiently.
      *
+     * <p>By default, documents are visible on platform surfaces. To opt out, call {@code
+     * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any
+     * visibility settings apply only to the schemas that are included in the {@code request}.
+     * Visibility settings for a schema type do not apply or persist across
+     * {@link SetSchemaRequest}s.
+     *
      * @param request The schema update request.
      * @param executor Executor on which to invoke the callback.
      * @param callback Callback to receive errors resulting from setting the schema. If the
      *                 operation succeeds, the callback will be invoked with {@code null}.
      */
+    // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
+    //  exposed.
     public void setSchema(
             @NonNull SetSchemaRequest request,
             @NonNull @CallbackExecutor Executor executor,
@@ -156,6 +165,43 @@
     }
 
     /**
+     * Retrieves the schema most recently successfully provided to {@link #setSchema}.
+     *
+     * @param executor Executor on which to invoke the callback.
+     * @param callback Callback to receive the pending results of schema.
+     */
+    public void getSchema(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull Consumer<AppSearchResult<Set<AppSearchSchema>>> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+        try {
+            mService.getSchema(
+                    mDatabaseName,
+                    new IAppSearchResultCallback.Stub() {
+                        public void onResult(AppSearchResult result) {
+                            executor.execute(() -> {
+                                if (result.isSuccess()) {
+                                    List<Bundle> schemaBundles =
+                                            (List<Bundle>) result.getResultValue();
+                                    Set<AppSearchSchema> schemas = new ArraySet<>(
+                                            schemaBundles.size());
+                                    for (int i = 0; i < schemaBundles.size(); i++) {
+                                        schemas.add(new AppSearchSchema(schemaBundles.get(i)));
+                                    }
+                                    callback.accept(AppSearchResult.newSuccessfulResult(schemas));
+                                } else {
+                                    callback.accept(result);
+                                }
+                            });
+                        }
+                    });
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Indexes documents into AppSearch.
      *
      * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
@@ -167,9 +213,9 @@
      *                 of the returned {@link AppSearchBatchResult} are the URIs of the input
      *                 documents. The values are {@code null} if they were successfully indexed,
      *                 or a failed {@link AppSearchResult} otherwise.
-     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with an
-     *                 {@link AppSearchException} if an error occurred in AppSearch initialization
-     *                 or a cause {@link Throwable} if other error occurred in AppSearch service.
+     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with a
+     *                 {@link Throwable} if an unexpected internal error occurred in AppSearch
+     *                 service.
      */
     public void putDocuments(
             @NonNull PutDocumentsRequest request,
@@ -210,9 +256,9 @@
      *                 {@link AppSearchResult} otherwise. URIs that are not found will return a
      *                 failed {@link AppSearchResult} with a result code of
      *                 {@link AppSearchResult#RESULT_NOT_FOUND}.
-     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with an
-     *                 {@link AppSearchException} if an error occurred in AppSearch initialization
-     *                 or a cause {@link Throwable} if other error occurred in AppSearch service.
+     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with a
+     *                 {@link Throwable} if an unexpected internal error occurred in AppSearch
+     *                 service.
      */
     public void getByUri(
             @NonNull GetByUriRequest request,
@@ -338,9 +384,9 @@
      *                 are {@code null} on success, or a failed {@link AppSearchResult} otherwise.
      *                 URIs that are not found will return a failed {@link AppSearchResult} with a
      *                 result code of {@link AppSearchResult#RESULT_NOT_FOUND}.
-     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with an
-     *                 {@link AppSearchException} if an error occurred in AppSearch initialization
-     *                 or a cause {@link Throwable} if other error occurred in AppSearch service.
+     *                 Or {@link BatchResultCallback#onSystemError} will be invoked with a
+     *                 {@link Throwable} if an unexpected internal error occurred in AppSearch
+     *                 service.
      */
     public void removeByUri(
             @NonNull RemoveByUriRequest request,
@@ -369,7 +415,7 @@
     /**
      * Removes {@link GenericDocument}s from the index by Query. Documents will be removed if they
      * match the {@code queryExpression} in given namespaces and schemaTypes which is set via
-     * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchema}.
+     * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchemaType}.
      *
      * <p> An empty {@code queryExpression} matches all documents.
      *
@@ -377,10 +423,13 @@
      * the current database.
      *
      * @param queryExpression Query String to search.
-     * @param searchSpec Defines what and how to remove
-     * @param executor Executor on which to invoke the callback.
-     * @param callback Callback to receive errors resulting from removing the documents. If the
-     *                 operation succeeds, the callback will be invoked with {@code null}.
+     * @param searchSpec      Spec containing schemaTypes, namespaces and query expression indicates
+     *                        how document will be removed. All specific about how to scoring,
+     *                        ordering, snippeting and resulting will be ignored.
+     * @param executor        Executor on which to invoke the callback.
+     * @param callback        Callback to receive errors resulting from removing the documents. If
+     *                        the operation succeeds, the callback will be invoked with
+     *                        {@code null}.
      */
     public void removeByQuery(@NonNull String queryExpression,
             @NonNull SearchSpec searchSpec,
diff --git a/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
index 1689e02..49049b6 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
@@ -16,13 +16,15 @@
 
 package android.app.appsearch;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
 /**
  * The callback interface to return {@link AppSearchBatchResult}.
  *
  * @param <KeyType> The type of the keys for {@link AppSearchBatchResult#getSuccesses} and
  * {@link AppSearchBatchResult#getFailures}.
  * @param <ValueType> The type of result objects associated with the keys.
- * @hide
  */
 public interface BatchResultCallback<KeyType, ValueType> {
 
@@ -31,15 +33,14 @@
      *
      * @param result The result of the executed request.
      */
-    void onResult(AppSearchBatchResult<KeyType, ValueType> result);
-
+    void onResult(@NonNull AppSearchBatchResult<KeyType, ValueType> result);
 
     /**
      * Called when a system error occurred.
      *
      * @param throwable The cause throwable.
      */
-    default void onSystemError(Throwable throwable) {
+    default void onSystemError(@Nullable Throwable throwable) {
         if (throwable != null) {
             throw new RuntimeException(throwable);
         }
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index d2aa8ea..1c56a9b 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -19,6 +19,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.RemoteException;
 
 import java.util.Objects;
@@ -31,6 +32,7 @@
  * <p>Apps can retrieve indexed documents through the query API.
  * @hide
  */
+@SystemApi
 public class GlobalSearchSession {
 
     private final IAppSearchManager mService;
@@ -115,7 +117,7 @@
      * @return The search result of performing this operation.
      */
     @NonNull
-    public SearchResults globalQuery(
+    public SearchResults query(
             @NonNull String queryExpression,
             @NonNull SearchSpec searchSpec,
             @NonNull @CallbackExecutor Executor executor) {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 1d7cb87..7883046 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -28,10 +28,10 @@
 /** {@hide} */
 interface IAppSearchManager {
     /**
-     * Sets the schema.
+     * Updates the AppSearch schema for this database.
      *
-     * @param databaseName  The databaseName this document resides in.
-     * @param schemaBundles List of AppSearchSchema bundles.
+     * @param databaseName  The name of the database where this schema lives.
+     * @param schemaBundles List of {@link AppSearchSchema} bundles.
      * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
      *     surfaces.
      * @param forceOverride Whether to apply the new schema even if it is incompatible. All
@@ -46,6 +46,17 @@
         boolean forceOverride,
         in IAppSearchResultCallback callback);
 
+
+    /**
+     * Retrieves the AppSearch schema for this database.
+     *
+     * @param databaseName  The name of the database to retrieve.
+     * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
+     *     {@link AppSearchResult}&lt;{@link List}&lt;{@link Bundle}&gt;&gt;, where the value are
+     *     AppSearchSchema bundle.
+     */
+    void getSchema(in String databaseName, in IAppSearchResultCallback callback);
+
     /**
      * Inserts documents into the index.
      *
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index 8548d20..7dc13b4 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -39,7 +39,6 @@
  * <p>Should close this object after finish fetching results.
  *
  * <p>This class is not thread safe.
- * @hide
  */
 public class SearchResults implements Closeable {
     private static final String TAG = "SearchResults";
@@ -77,7 +76,7 @@
      * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an
      * empty list.
      *
-     * <p>The page size is set by {@link SearchSpec.Builder#setNumPerPage}.
+     * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}.
      *
      * @param callback Callback to receive the pending result of performing this operation.
      */
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
new file mode 100644
index 0000000..b567dee
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch;
+
+import android.annotation.NonNull;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * This class represents a uniquely identifiable package.
+ *
+ * @hide
+ */
+public class PackageIdentifier {
+    public final String packageName;
+    public final byte[] certificate;
+
+    /**
+     * Creates a unique identifier for a package.
+     *
+     * @param packageName Name of the package.
+     * @param certificate SHA256 certificate digest of the package.
+     */
+    public PackageIdentifier(@NonNull String packageName, @NonNull byte[] certificate) {
+        this.packageName = packageName;
+        this.certificate = certificate;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || !(obj instanceof PackageIdentifier)) {
+            return false;
+        }
+        final PackageIdentifier other = (PackageIdentifier) obj;
+        return this.packageName.equals(other.packageName)
+                && Arrays.equals(this.certificate, other.certificate);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(packageName, Arrays.hashCode(certificate));
+    }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
index be6d157..a04da34 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
@@ -46,7 +46,7 @@
         return mNamespace;
     }
 
-    /** Returns the URIs to remove from the namespace. */
+    /** Returns the URIs of documents to remove from the namespace. */
     @NonNull
     public Set<String> getUris() {
         return Collections.unmodifiableSet(mUris);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
index 0e03131..4ef30c3 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.app.appsearch.exceptions.AppSearchException;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import com.android.internal.util.Preconditions;
@@ -28,6 +29,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -38,14 +40,17 @@
 public final class SetSchemaRequest {
     private final Set<AppSearchSchema> mSchemas;
     private final Set<String> mSchemasNotPlatformSurfaceable;
+    private final Map<String, Set<PackageIdentifier>> mSchemasPackageAccessible;
     private final boolean mForceOverride;
 
     SetSchemaRequest(
             @NonNull Set<AppSearchSchema> schemas,
             @NonNull Set<String> schemasNotPlatformSurfaceable,
+            @NonNull Map<String, Set<PackageIdentifier>> schemasPackageAccessible,
             boolean forceOverride) {
         mSchemas = Preconditions.checkNotNull(schemas);
         mSchemasNotPlatformSurfaceable = Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
+        mSchemasPackageAccessible = Preconditions.checkNotNull(schemasPackageAccessible);
         mForceOverride = forceOverride;
     }
 
@@ -65,6 +70,39 @@
         return Collections.unmodifiableSet(mSchemasNotPlatformSurfaceable);
     }
 
+    /**
+     * Returns a mapping of schema types to the set of packages that have access to that schema
+     * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
+     * certificate.
+     *
+     * <p>This method is inefficient to call repeatedly.
+     *
+     * @hide
+     */
+    @NonNull
+    public Map<String, Set<PackageIdentifier>> getSchemasPackageAccessible() {
+        Map<String, Set<PackageIdentifier>> copy = new ArrayMap<>();
+        for (String key : mSchemasPackageAccessible.keySet()) {
+            copy.put(key, new ArraySet<>(mSchemasPackageAccessible.get(key)));
+        }
+        return copy;
+    }
+
+    /**
+     * Returns a mapping of schema types to the set of packages that have access to that schema
+     * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
+     * certificate.
+     *
+     * <p>A more efficient version of {@code #getSchemasPackageAccessible}, but it returns a
+     * modifiable map. This is not meant to be unhidden and should only be used by internal classes.
+     *
+     * @hide
+     */
+    @NonNull
+    public Map<String, Set<PackageIdentifier>> getSchemasPackageAccessibleInternal() {
+        return mSchemasPackageAccessible;
+    }
+
     /** Returns whether this request will force the schema to be overridden. */
     public boolean isForceOverride() {
         return mForceOverride;
@@ -74,6 +112,8 @@
     public static final class Builder {
         private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
         private final Set<String> mSchemasNotPlatformSurfaceable = new ArraySet<>();
+        private final Map<String, Set<PackageIdentifier>> mSchemasPackageAccessible =
+                new ArrayMap<>();
         private boolean mForceOverride = false;
         private boolean mBuilt = false;
 
@@ -102,32 +142,62 @@
         }
 
         /**
-         * Sets visibility on system UI surfaces for schema types.
+         * Sets visibility on system UI surfaces for the given {@code schemaType}.
          *
+         * @param schemaType The schema type to set visibility on.
+         * @param visible Whether the {@code schemaType} will be visible or not.
          * @hide
          */
         @NonNull
         public Builder setSchemaTypeVisibilityForSystemUi(
-                boolean visible, @NonNull String... schemaTypes) {
-            Preconditions.checkNotNull(schemaTypes);
-            return this.setSchemaTypeVisibilityForSystemUi(visible, Arrays.asList(schemaTypes));
+                @NonNull String schemaType, boolean visible) {
+            Preconditions.checkNotNull(schemaType);
+            Preconditions.checkState(!mBuilt, "Builder has already been used");
+
+            if (visible) {
+                mSchemasNotPlatformSurfaceable.remove(schemaType);
+            } else {
+                mSchemasNotPlatformSurfaceable.add(schemaType);
+            }
+            return this;
         }
 
         /**
-         * Sets visibility on system UI surfaces for schema types.
+         * Sets visibility for a package for the given {@code schemaType}.
          *
+         * @param schemaType The schema type to set visibility on.
+         * @param visible Whether the {@code schemaType} will be visible or not.
+         * @param packageIdentifier Represents the package that will be granted visibility.
          * @hide
          */
         @NonNull
-        public Builder setSchemaTypeVisibilityForSystemUi(
-                boolean visible, @NonNull Collection<String> schemaTypes) {
+        public Builder setSchemaTypeVisibilityForPackage(
+                @NonNull String schemaType,
+                boolean visible,
+                @NonNull PackageIdentifier packageIdentifier) {
+            Preconditions.checkNotNull(schemaType);
+            Preconditions.checkNotNull(packageIdentifier);
             Preconditions.checkState(!mBuilt, "Builder has already been used");
-            Preconditions.checkNotNull(schemaTypes);
+
+            Set<PackageIdentifier> packageIdentifiers = mSchemasPackageAccessible.get(schemaType);
             if (visible) {
-                mSchemasNotPlatformSurfaceable.removeAll(schemaTypes);
+                if (packageIdentifiers == null) {
+                    packageIdentifiers = new ArraySet<>();
+                }
+                packageIdentifiers.add(packageIdentifier);
+                mSchemasPackageAccessible.put(schemaType, packageIdentifiers);
             } else {
-                mSchemasNotPlatformSurfaceable.addAll(schemaTypes);
+                if (packageIdentifiers == null) {
+                    // Return early since there was nothing set to begin with.
+                    return this;
+                }
+                packageIdentifiers.remove(packageIdentifier);
+                if (packageIdentifiers.isEmpty()) {
+                    // Remove the entire key so that we don't have empty sets as values.
+                    mSchemasPackageAccessible.remove(schemaType);
+                }
             }
+
             return this;
         }
 
@@ -159,21 +229,24 @@
 
             // Verify that any schema types with visibility settings refer to a real schema.
             // Create a copy because we're going to remove from the set for verification purposes.
-            Set<String> schemasNotPlatformSurfaceableCopy =
-                    new ArraySet<>(mSchemasNotPlatformSurfaceable);
+            Set<String> referencedSchemas = new ArraySet<>(mSchemasNotPlatformSurfaceable);
+            referencedSchemas.addAll(mSchemasPackageAccessible.keySet());
+
             for (AppSearchSchema schema : mSchemas) {
-                schemasNotPlatformSurfaceableCopy.remove(schema.getSchemaType());
+                referencedSchemas.remove(schema.getSchemaType());
             }
-            if (!schemasNotPlatformSurfaceableCopy.isEmpty()) {
+            if (!referencedSchemas.isEmpty()) {
                 // We still have schema types that weren't seen in our mSchemas set. This means
                 // there wasn't a corresponding AppSearchSchema.
                 throw new IllegalArgumentException(
-                        "Schema types "
-                                + schemasNotPlatformSurfaceableCopy
-                                + " referenced, but were not added.");
+                        "Schema types " + referencedSchemas + " referenced, but were not added.");
             }
 
-            return new SetSchemaRequest(mSchemas, mSchemasNotPlatformSurfaceable, mForceOverride);
+            return new SetSchemaRequest(
+                    mSchemas,
+                    mSchemasNotPlatformSurfaceable,
+                    mSchemasPackageAccessible,
+                    mForceOverride);
         }
     }
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 551347c..d81b794 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -47,7 +47,6 @@
  */
 public class AppSearchManagerService extends SystemService {
     private static final String TAG = "AppSearchManagerService";
-    private static final char CALLING_NAME_DATABASE_DELIMITER = '$';
 
     public AppSearchManagerService(Context context) {
         super(context);
@@ -78,8 +77,9 @@
                     schemas.add(new AppSearchSchema(schemaBundles.get(i)));
                 }
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
-                impl.setSchema(databaseName, schemas, schemasNotPlatformSurfaceable, forceOverride);
+                String packageName = convertUidToPackageName(callingUid);
+                impl.setSchema(packageName, databaseName, schemas, schemasNotPlatformSurfaceable,
+                        forceOverride);
                 invokeCallbackOnResult(callback,
                         AppSearchResult.newSuccessfulResult(/*result=*/ null));
             } catch (Throwable t) {
@@ -90,6 +90,32 @@
         }
 
         @Override
+        public void getSchema(
+                @NonNull String databaseName,
+                @NonNull IAppSearchResultCallback callback) {
+            Preconditions.checkNotNull(databaseName);
+            Preconditions.checkNotNull(callback);
+            int callingUid = Binder.getCallingUidOrThrow();
+            int callingUserId = UserHandle.getUserId(callingUid);
+            final long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
+                String packageName = convertUidToPackageName(callingUid);
+                List<AppSearchSchema> schemas = impl.getSchema(packageName, databaseName);
+                List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
+                for (int i = 0; i < schemas.size(); i++) {
+                    schemaBundles.add(schemas.get(i).getBundle());
+                }
+                invokeCallbackOnResult(callback,
+                        AppSearchResult.newSuccessfulResult(schemaBundles));
+            } catch (Throwable t) {
+                invokeCallbackOnError(callback, t);
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        @Override
         public void putDocuments(
                 @NonNull String databaseName,
                 @NonNull List<Bundle> documentBundles,
@@ -104,13 +130,13 @@
                 AppSearchBatchResult.Builder<String, Void> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+                String packageName = convertUidToPackageName(callingUid);
                 for (int i = 0; i < documentBundles.size(); i++) {
                     GenericDocument document = new GenericDocument(documentBundles.get(i));
                     try {
                         // TODO(b/173451571): reduce burden of binder thread by enqueue request onto
                         // a separate thread.
-                        impl.putDocument(databaseName, document);
+                        impl.putDocument(packageName, databaseName, document);
                         resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
                     } catch (Throwable t) {
                         resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
@@ -139,11 +165,12 @@
                 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
                         new AppSearchBatchResult.Builder<>();
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+                String packageName = convertUidToPackageName(callingUid);
                 for (int i = 0; i < uris.size(); i++) {
                     String uri = uris.get(i);
                     try {
-                        GenericDocument document = impl.getDocument(databaseName, namespace, uri);
+                        GenericDocument document = impl.getDocument(packageName, databaseName,
+                                namespace, uri);
                         resultBuilder.setSuccess(uri, document.getBundle());
                     } catch (Throwable t) {
                         resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -173,8 +200,9 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+                String packageName = convertUidToPackageName(callingUid);
                 SearchResultPage searchResultPage = impl.query(
+                        packageName,
                         databaseName,
                         queryExpression,
                         new SearchSpec(searchSpecBundle));
@@ -257,15 +285,15 @@
             int callingUid = Binder.getCallingUidOrThrow();
             int callingUserId = UserHandle.getUserId(callingUid);
             final long callingIdentity = Binder.clearCallingIdentity();
-            AppSearchBatchResult.Builder<String, Void> resultBuilder =
-                    new AppSearchBatchResult.Builder<>();
             try {
+                AppSearchBatchResult.Builder<String, Void> resultBuilder =
+                        new AppSearchBatchResult.Builder<>();
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+                String packageName = convertUidToPackageName(callingUid);
                 for (int i = 0; i < uris.size(); i++) {
                     String uri = uris.get(i);
                     try {
-                        impl.remove(databaseName, namespace, uri);
+                        impl.remove(packageName, databaseName, namespace, uri);
                         resultBuilder.setSuccess(uri, /*result= */null);
                     } catch (Throwable t) {
                         resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -294,8 +322,8 @@
             final long callingIdentity = Binder.clearCallingIdentity();
             try {
                 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
-                databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
-                impl.removeByQuery(databaseName, queryExpression,
+                String packageName = convertUidToPackageName(callingUid);
+                impl.removeByQuery(packageName, databaseName, queryExpression,
                         new SearchSpec(searchSpecBundle));
                 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
             } catch (Throwable t) {
@@ -322,13 +350,13 @@
         }
 
         /**
-         * Rewrites the database name by adding a prefix of unique name for the given uid.
+         * Returns a package name for the given uid.
          *
          * <p>The current implementation returns the package name of the app with this uid in a
          * format like {@code com.example.package} or {@code com.example.sharedname:5678}.
          */
         @NonNull
-        private String rewriteDatabaseNameWithUid(String databaseName, int callingUid) {
+        private String convertUidToPackageName(int callingUid) {
             // For regular apps, this call will return the package name. If callingUid is an
             // android:sharedUserId, this value may be another type of name and have a :uid suffix.
             String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
@@ -337,12 +365,12 @@
                 throw new IllegalStateException(
                         "Failed to look up package name for uid " + callingUid);
             }
-            return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName;
+            return callingUidName;
         }
 
-        /**  Invokes the {@link IAppSearchResultCallback} with the result. */
+        /** Invokes the {@link IAppSearchResultCallback} with the result. */
         private void invokeCallbackOnResult(IAppSearchResultCallback callback,
-                AppSearchResult result) {
+                AppSearchResult<?> result) {
             try {
                 callback.onResult(result);
             } catch (RemoteException e) {
@@ -350,9 +378,9 @@
             }
         }
 
-        /**  Invokes the {@link IAppSearchBatchResultCallback} with the result. */
+        /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
         private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback,
-                AppSearchBatchResult result) {
+                AppSearchBatchResult<?, ?> result) {
             try {
                 callback.onResult(result);
             } catch (RemoteException e) {
@@ -361,9 +389,9 @@
         }
 
         /**
-         *  Invokes the {@link IAppSearchResultCallback} with an throwable.
+         * Invokes the {@link IAppSearchResultCallback} with an throwable.
          *
-         *  <p>The throwable is convert to a {@link AppSearchResult};
+         * <p>The throwable is convert to a {@link AppSearchResult};
          */
         private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
             try {
@@ -374,7 +402,7 @@
         }
 
         /**
-         *  Invokes the {@link IAppSearchBatchResultCallback} with an throwable.
+         * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
          *
          * <p>The throwable is converted to {@link ParcelableException}.
          */
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 62b81d0..c806af5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -75,15 +75,17 @@
  *
  * <p>Never create two instances using the same folder.
  *
- * <p>A single instance of {@link AppSearchImpl} can support all databases. Schemas and documents
- * are physically saved together in {@link IcingSearchEngine}, but logically isolated:
+ * <p>A single instance of {@link AppSearchImpl} can support all packages and databases. This is
+ * done by combining the package and database name into a unique prefix and prefixing the schemas
+ * and documents stored under that owner. Schemas and documents are physically saved together in
+ * {@link IcingSearchEngine}, but logically isolated:
  *
  * <ul>
- *   <li>Rewrite SchemaType in SchemaProto by adding database name prefix and save into SchemaTypes
- *       set in {@link #setSchema}.
- *   <li>Rewrite namespace and SchemaType in DocumentProto by adding database name prefix and save
- *       to namespaces set in {@link #putDocument}.
- *   <li>Remove database name prefix when retrieve documents in {@link #getDocument} and {@link
+ *   <li>Rewrite SchemaType in SchemaProto by adding the package-database prefix and save into
+ *       SchemaTypes set in {@link #setSchema}.
+ *   <li>Rewrite namespace and SchemaType in DocumentProto by adding package-database prefix and
+ *       save to namespaces set in {@link #putDocument}.
+ *   <li>Remove package-database prefix when retrieving documents in {@link #getDocument} and {@link
  *       #query}.
  *   <li>Rewrite filters in {@link SearchSpecProto} to have all namespaces and schema types of the
  *       queried database when user using empty filters in {@link #query}.
@@ -108,6 +110,8 @@
 
     @VisibleForTesting static final char DATABASE_DELIMITER = '/';
 
+    @VisibleForTesting static final char PACKAGE_DELIMITER = '$';
+
     @VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
     @VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
     @VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
@@ -120,12 +124,14 @@
     @GuardedBy("mReadWriteLock")
     private final VisibilityStore mVisibilityStoreLocked;
 
-    // The map contains schemaTypes and namespaces for all database. All values in the map have
-    // the database name prefix.
+    // This map contains schemaTypes for all package-database prefixes. All values in the map are
+    // prefixed with the package-database prefix.
     // TODO(b/172360376): Check if this can be replaced with an ArrayMap
     @GuardedBy("mReadWriteLock")
     private final Map<String, Set<String>> mSchemaMapLocked = new HashMap<>();
 
+    // This map contains namespaces for all package-database prefixes. All values in the map are
+    // prefixed with the package-database prefix.
     // TODO(b/172360376): Check if this can be replaced with an ArrayMap
     @GuardedBy("mReadWriteLock")
     private final Map<String, Set<String>> mNamespaceMapLocked = new HashMap<>();
@@ -179,19 +185,13 @@
 
             // Populate schema map
             for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
-                String qualifiedSchemaType = schema.getSchemaType();
-                addToMap(
-                        mSchemaMapLocked,
-                        getDatabaseName(qualifiedSchemaType),
-                        qualifiedSchemaType);
+                String prefixedSchemaType = schema.getSchemaType();
+                addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), prefixedSchemaType);
             }
 
             // Populate namespace map
-            for (String qualifiedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
-                addToMap(
-                        mNamespaceMapLocked,
-                        getDatabaseName(qualifiedNamespace),
-                        qualifiedNamespace);
+            for (String prefixedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
+                addToMap(mNamespaceMapLocked, getPrefix(prefixedNamespace), prefixedNamespace);
             }
 
             // TODO(b/155939114): It's possible to optimize after init, which would reduce the time
@@ -225,6 +225,7 @@
      *
      * <p>This method belongs to mutate group.
      *
+     * @param packageName The package name that owns the schemas.
      * @param databaseName The name of the database where this schema lives.
      * @param schemas Schemas to set for this app.
      * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
@@ -234,6 +235,7 @@
      * @throws AppSearchException on IcingSearchEngine error.
      */
     public void setSchema(
+            @NonNull String packageName,
             @NonNull String databaseName,
             @NonNull List<AppSearchSchema> schemas,
             @NonNull List<String> schemasNotPlatformSurfaceable,
@@ -250,10 +252,11 @@
                 newSchemaBuilder.addTypes(schemaTypeProto);
             }
 
-            // Combine the existing schema (which may have types from other databases) with this
-            // database's new schema. Modifies the existingSchemaBuilder.
+            String prefix = createPrefix(packageName, databaseName);
+            // Combine the existing schema (which may have types from other prefixes) with this
+            // prefix's new schema. Modifies the existingSchemaBuilder.
             RewrittenSchemaResults rewrittenSchemaResults =
-                    rewriteSchema(databaseName, existingSchemaBuilder, newSchemaBuilder.build());
+                    rewriteSchema(prefix, existingSchemaBuilder, newSchemaBuilder.build());
 
             // Apply schema
             SetSchemaResultProto setSchemaResultProto =
@@ -280,17 +283,15 @@
             }
 
             // Update derived data structures.
-            mSchemaMapLocked.put(databaseName, rewrittenSchemaResults.mRewrittenQualifiedTypes);
+            mSchemaMapLocked.put(prefix, rewrittenSchemaResults.mRewrittenPrefixedTypes);
 
-            String databasePrefix = getDatabasePrefix(databaseName);
-            Set<String> qualifiedSchemasNotPlatformSurfaceable =
+            Set<String> prefixedSchemasNotPlatformSurfaceable =
                     new ArraySet<>(schemasNotPlatformSurfaceable.size());
             for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
-                qualifiedSchemasNotPlatformSurfaceable.add(
-                        databasePrefix + schemasNotPlatformSurfaceable.get(i));
+                prefixedSchemasNotPlatformSurfaceable.add(
+                        prefix + schemasNotPlatformSurfaceable.get(i));
             }
-            mVisibilityStoreLocked.setVisibility(
-                    databaseName, qualifiedSchemasNotPlatformSurfaceable);
+            mVisibilityStoreLocked.setVisibility(prefix, prefixedSchemasNotPlatformSurfaceable);
 
             // Determine whether to schedule an immediate optimize.
             if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
@@ -307,15 +308,17 @@
     }
 
     /**
-     * Retrieves the AppSearch schema for this database.
+     * Retrieves the AppSearch schema for this package name, database.
      *
      * <p>This method belongs to query group.
      *
+     * @param packageName Package name that owns this schema
      * @param databaseName The name of the database where this schema lives.
      * @throws AppSearchException on IcingSearchEngine error.
      */
     @NonNull
-    public List<AppSearchSchema> getSchema(@NonNull String databaseName) throws AppSearchException {
+    public List<AppSearchSchema> getSchema(
+            @NonNull String packageName, @NonNull String databaseName) throws AppSearchException {
         SchemaProto fullSchema;
         mReadWriteLock.readLock().lock();
         try {
@@ -324,16 +327,16 @@
             mReadWriteLock.readLock().unlock();
         }
 
+        String prefix = createPrefix(packageName, databaseName);
         List<AppSearchSchema> result = new ArrayList<>();
         for (int i = 0; i < fullSchema.getTypesCount(); i++) {
-            String typeDatabase = getDatabaseName(fullSchema.getTypes(i).getSchemaType());
-            if (!databaseName.equals(typeDatabase)) {
+            String typePrefix = getPrefix(fullSchema.getTypes(i).getSchemaType());
+            if (!prefix.equals(typePrefix)) {
                 continue;
             }
             // Rewrite SchemaProto.types.schema_type
             SchemaTypeConfigProto.Builder typeConfigBuilder = fullSchema.getTypes(i).toBuilder();
-            String newSchemaType =
-                    typeConfigBuilder.getSchemaType().substring(databaseName.length() + 1);
+            String newSchemaType = typeConfigBuilder.getSchemaType().substring(prefix.length());
             typeConfigBuilder.setSchemaType(newSchemaType);
 
             // Rewrite SchemaProto.types.properties.schema_type
@@ -344,9 +347,7 @@
                         typeConfigBuilder.getProperties(propertyIdx).toBuilder();
                 if (!propertyConfigBuilder.getSchemaType().isEmpty()) {
                     String newPropertySchemaType =
-                            propertyConfigBuilder
-                                    .getSchemaType()
-                                    .substring(databaseName.length() + 1);
+                            propertyConfigBuilder.getSchemaType().substring(prefix.length());
                     propertyConfigBuilder.setSchemaType(newPropertySchemaType);
                     typeConfigBuilder.setProperties(propertyIdx, propertyConfigBuilder);
                 }
@@ -363,21 +364,26 @@
      *
      * <p>This method belongs to mutate group.
      *
+     * @param packageName The package name that owns this document.
      * @param databaseName The databaseName this document resides in.
      * @param document The document to index.
      * @throws AppSearchException on IcingSearchEngine error.
      */
-    public void putDocument(@NonNull String databaseName, @NonNull GenericDocument document)
+    public void putDocument(
+            @NonNull String packageName,
+            @NonNull String databaseName,
+            @NonNull GenericDocument document)
             throws AppSearchException {
         DocumentProto.Builder documentBuilder =
                 GenericDocumentToProtoConverter.toDocumentProto(document).toBuilder();
-        addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName));
+        String prefix = createPrefix(packageName, databaseName);
+        addPrefixToDocument(documentBuilder, prefix);
 
         PutResultProto putResultProto;
         mReadWriteLock.writeLock().lock();
         try {
             putResultProto = mIcingSearchEngineLocked.put(documentBuilder.build());
-            addToMap(mNamespaceMapLocked, databaseName, documentBuilder.getNamespace());
+            addToMap(mNamespaceMapLocked, prefix, documentBuilder.getNamespace());
             // The existing documents with same URI will be deleted, so there maybe some resources
             // could be released after optimize().
             checkForOptimizeLocked(/* force= */ false);
@@ -392,6 +398,7 @@
      *
      * <p>This method belongs to query group.
      *
+     * @param packageName The package that owns this document.
      * @param databaseName The databaseName this document resides in.
      * @param namespace The namespace this document resides in.
      * @param uri The URI of the document to get.
@@ -400,20 +407,24 @@
      */
     @NonNull
     public GenericDocument getDocument(
-            @NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+            @NonNull String packageName,
+            @NonNull String databaseName,
+            @NonNull String namespace,
+            @NonNull String uri)
             throws AppSearchException {
         GetResultProto getResultProto;
         mReadWriteLock.readLock().lock();
         try {
             getResultProto =
-                    mIcingSearchEngineLocked.get(getDatabasePrefix(databaseName) + namespace, uri);
+                    mIcingSearchEngineLocked.get(
+                            createPrefix(packageName, databaseName) + namespace, uri);
         } finally {
             mReadWriteLock.readLock().unlock();
         }
         checkSuccess(getResultProto.getStatus());
 
         DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
-        removeDatabasesFromDocument(documentBuilder);
+        removePrefixesFromDocument(documentBuilder);
         return GenericDocumentToProtoConverter.toGenericDocument(documentBuilder.build());
     }
 
@@ -422,6 +433,7 @@
      *
      * <p>This method belongs to query group.
      *
+     * @param packageName The package name that is performing the query.
      * @param databaseName The databaseName this query for.
      * @param queryExpression Query String to search.
      * @param searchSpec Spec for setting filters, raw query etc.
@@ -431,20 +443,24 @@
      */
     @NonNull
     public SearchResultPage query(
+            @NonNull String packageName,
             @NonNull String databaseName,
             @NonNull String queryExpression,
             @NonNull SearchSpec searchSpec)
             throws AppSearchException {
         mReadWriteLock.readLock().lock();
         try {
-            return doQueryLocked(Collections.singleton(databaseName), queryExpression, searchSpec);
+            return doQueryLocked(
+                    Collections.singleton(createPrefix(packageName, databaseName)),
+                    queryExpression,
+                    searchSpec);
         } finally {
             mReadWriteLock.readLock().unlock();
         }
     }
 
     /**
-     * Executes a global query, i.e. over all permitted databases, against the AppSearch index and
+     * Executes a global query, i.e. over all permitted prefixes, against the AppSearch index and
      * returns results.
      *
      * <p>This method belongs to query group.
@@ -464,9 +480,15 @@
         //  verified.
         mReadWriteLock.readLock().lock();
         try {
-            // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
+            // We use the mNamespaceMap.keySet here because it's the smaller set of valid prefixes
             // that could exist.
-            return doQueryLocked(mNamespaceMapLocked.keySet(), queryExpression, searchSpec);
+            Set<String> prefixes = mNamespaceMapLocked.keySet();
+
+            // Filter out any VisibilityStore documents which are AppSearch-internal only.
+            prefixes.remove(
+                    createPrefix(VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
+
+            return doQueryLocked(prefixes, queryExpression, searchSpec);
         } finally {
             mReadWriteLock.readLock().unlock();
         }
@@ -474,7 +496,7 @@
 
     @GuardedBy("mReadWriteLock")
     private SearchResultPage doQueryLocked(
-            @NonNull Set<String> databases,
+            @NonNull Set<String> prefixes,
             @NonNull String queryExpression,
             @NonNull SearchSpec searchSpec)
             throws AppSearchException {
@@ -486,12 +508,10 @@
         ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
         SearchResultProto searchResultProto;
 
-        // rewriteSearchSpecForDatabases will return false if none of the databases that the
+        // rewriteSearchSpecForPrefixesLocked will return false if none of the prefixes that the
         // client is trying to search on exist, so we can return an empty SearchResult and skip
         // sending request to Icing.
-        // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
-        // that could exist.
-        if (!rewriteSearchSpecForDatabasesLocked(searchSpecBuilder, databases)) {
+        if (!rewriteSearchSpecForPrefixesLocked(searchSpecBuilder, prefixes)) {
             return new SearchResultPage(Bundle.EMPTY);
         }
         searchResultProto =
@@ -546,18 +566,23 @@
      *
      * <p>This method belongs to mutate group.
      *
+     * @param packageName The package name that owns the document.
      * @param databaseName The databaseName the document is in.
      * @param namespace Namespace of the document to remove.
      * @param uri URI of the document to remove.
      * @throws AppSearchException on IcingSearchEngine error.
      */
-    public void remove(@NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+    public void remove(
+            @NonNull String packageName,
+            @NonNull String databaseName,
+            @NonNull String namespace,
+            @NonNull String uri)
             throws AppSearchException {
-        String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
+        String prefixedNamespace = createPrefix(packageName, databaseName) + namespace;
         DeleteResultProto deleteResultProto;
         mReadWriteLock.writeLock().lock();
         try {
-            deleteResultProto = mIcingSearchEngineLocked.delete(qualifiedNamespace, uri);
+            deleteResultProto = mIcingSearchEngineLocked.delete(prefixedNamespace, uri);
             checkForOptimizeLocked(/* force= */ false);
         } finally {
             mReadWriteLock.writeLock().unlock();
@@ -570,12 +595,14 @@
      *
      * <p>This method belongs to mutate group.
      *
+     * @param packageName The package name that owns the documents.
      * @param databaseName The databaseName the document is in.
      * @param queryExpression Query String to search.
      * @param searchSpec Defines what and how to remove
      * @throws AppSearchException on IcingSearchEngine error.
      */
     public void removeByQuery(
+            @NonNull String packageName,
             @NonNull String databaseName,
             @NonNull String queryExpression,
             @NonNull SearchSpec searchSpec)
@@ -586,11 +613,12 @@
         DeleteResultProto deleteResultProto;
         mReadWriteLock.writeLock().lock();
         try {
-            // Only rewrite SearchSpec for non empty database.
-            // rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we
+            // Only rewrite SearchSpec for non empty prefixes.
+            // rewriteSearchSpecForPrefixesLocked will return false for empty prefixes, we
             // should skip sending request to Icing and return in here.
-            if (!rewriteSearchSpecForDatabasesLocked(
-                    searchSpecBuilder, Collections.singleton(databaseName))) {
+            if (!rewriteSearchSpecForPrefixesLocked(
+                    searchSpecBuilder,
+                    Collections.singleton(createPrefix(packageName, databaseName)))) {
                 return;
             }
             deleteResultProto = mIcingSearchEngineLocked.deleteByQuery(searchSpecBuilder.build());
@@ -605,7 +633,7 @@
     }
 
     /**
-     * Clears documents and schema across all databaseNames.
+     * Clears documents and schema across all packages and databaseNames.
      *
      * <p>This method belongs to mutate group.
      *
@@ -632,33 +660,30 @@
     /** Wrapper around schema changes */
     @VisibleForTesting
     static class RewrittenSchemaResults {
-        // Any database-qualified types that used to exist in the schema, but are deleted in the
-        // new one.
-        final Set<String> mDeletedQualifiedTypes = new ArraySet<>();
+        // Any prefixed types that used to exist in the schema, but are deleted in the new one.
+        final Set<String> mDeletedPrefixedTypes = new ArraySet<>();
 
-        // Database-qualified types that were part of the new schema.
-        final Set<String> mRewrittenQualifiedTypes = new ArraySet<>();
+        // Prefixed types that were part of the new schema.
+        final Set<String> mRewrittenPrefixedTypes = new ArraySet<>();
     }
 
     /**
      * Rewrites all types mentioned in the given {@code newSchema} to prepend {@code prefix}.
      * Rewritten types will be added to the {@code existingSchema}.
      *
-     * @param databaseName The name of the database where this schema lives.
-     * @param existingSchema A schema that may contain existing types from across all database
-     *     instances. Will be mutated to contain the properly rewritten schema types from {@code
-     *     newSchema}.
+     * @param prefix The full prefix to prepend to the schema.
+     * @param existingSchema A schema that may contain existing types from across all prefixes. Will
+     *     be mutated to contain the properly rewritten schema types from {@code newSchema}.
      * @param newSchema Schema with types to add to the {@code existingSchema}.
-     * @return a RewrittenSchemaResults contains all qualified schema type names in the given
-     *     database as well as a set of schema types that were deleted from the database.
+     * @return a RewrittenSchemaResults that contains all prefixed schema type names in the given
+     *     prefix as well as a set of schema types that were deleted.
      */
     @VisibleForTesting
     static RewrittenSchemaResults rewriteSchema(
-            @NonNull String databaseName,
+            @NonNull String prefix,
             @NonNull SchemaProto.Builder existingSchema,
             @NonNull SchemaProto newSchema)
             throws AppSearchException {
-        String prefix = getDatabasePrefix(databaseName);
         HashMap<String, SchemaTypeConfigProto> newTypesToProto = new HashMap<>();
         // Rewrite the schema type to include the typePrefix.
         for (int typeIdx = 0; typeIdx < newSchema.getTypesCount(); typeIdx++) {
@@ -687,10 +712,10 @@
 
         // newTypesToProto is modified below, so we need a copy first
         RewrittenSchemaResults rewrittenSchemaResults = new RewrittenSchemaResults();
-        rewrittenSchemaResults.mRewrittenQualifiedTypes.addAll(newTypesToProto.keySet());
+        rewrittenSchemaResults.mRewrittenPrefixedTypes.addAll(newTypesToProto.keySet());
 
-        // Combine the existing schema (which may have types from other databases) with this
-        // database's new schema. Modifies the existingSchemaBuilder.
+        // Combine the existing schema (which may have types from other prefixes) with this
+        // prefix's new schema. Modifies the existingSchemaBuilder.
         // Check if we need to replace any old schema types with the new ones.
         for (int i = 0; i < existingSchema.getTypesCount(); i++) {
             String schemaType = existingSchema.getTypes(i).getSchemaType();
@@ -698,11 +723,11 @@
             if (newProto != null) {
                 // Replacement
                 existingSchema.setTypes(i, newProto);
-            } else if (databaseName.equals(getDatabaseName(schemaType))) {
+            } else if (prefix.equals(getPrefix(schemaType))) {
                 // All types existing before but not in newSchema should be removed.
                 existingSchema.removeTypes(i);
                 --i;
-                rewrittenSchemaResults.mDeletedQualifiedTypes.add(schemaType);
+                rewrittenSchemaResults.mDeletedPrefixedTypes.add(schemaType);
             }
         }
         // We've been removing existing types from newTypesToProto, so everything that remains is
@@ -749,17 +774,16 @@
     }
 
     /**
-     * Removes any database names from types and namespaces mentioned anywhere in {@code
-     * documentBuilder}.
+     * Removes any prefixes from types and namespaces mentioned anywhere in {@code documentBuilder}.
      *
      * @param documentBuilder The document to mutate
      */
     @VisibleForTesting
-    static void removeDatabasesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
+    static void removePrefixesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
             throws AppSearchException {
         // Rewrite the type name and namespace to remove the prefix.
-        documentBuilder.setSchema(removeDatabasePrefix(documentBuilder.getSchema()));
-        documentBuilder.setNamespace(removeDatabasePrefix(documentBuilder.getNamespace()));
+        documentBuilder.setSchema(removePrefix(documentBuilder.getSchema()));
+        documentBuilder.setNamespace(removePrefix(documentBuilder.getNamespace()));
 
         // Recurse into derived documents
         for (int propertyIdx = 0;
@@ -772,7 +796,7 @@
                 for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
                     DocumentProto.Builder derivedDocumentBuilder =
                             propertyBuilder.getDocumentValues(documentIdx).toBuilder();
-                    removeDatabasesFromDocument(derivedDocumentBuilder);
+                    removePrefixesFromDocument(derivedDocumentBuilder);
                     propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
                 }
                 documentBuilder.setProperties(propertyIdx, propertyBuilder);
@@ -781,27 +805,25 @@
     }
 
     /**
-     * Rewrites the schemaTypeFilters and namespacesFilters that exist in {@code databaseNames}.
+     * Rewrites the schemaTypeFilters and namespacesFilters that exist with {@code prefixes}.
      *
-     * <p>If the searchSpec has empty filter lists, all existing databases from {@code
-     * databaseNames} will be added.
+     * <p>If the searchSpec has empty filter lists, all prefixes filters will be added.
      *
      * <p>This method should be only called in query methods and get the READ lock to keep thread
      * safety.
      *
-     * @return false if none of the requested databases exist.
+     * @return false if none of the requested prefixes exist.
      */
     @VisibleForTesting
     @GuardedBy("mReadWriteLock")
-    boolean rewriteSearchSpecForDatabasesLocked(
-            @NonNull SearchSpecProto.Builder searchSpecBuilder,
-            @NonNull Set<String> databaseNames) {
+    boolean rewriteSearchSpecForPrefixesLocked(
+            @NonNull SearchSpecProto.Builder searchSpecBuilder, @NonNull Set<String> prefixes) {
         // Create a copy since retainAll() modifies the original set.
-        Set<String> existingDatabases = new ArraySet<>(mNamespaceMapLocked.keySet());
-        existingDatabases.retainAll(databaseNames);
+        Set<String> existingPrefixes = new ArraySet<>(mNamespaceMapLocked.keySet());
+        existingPrefixes.retainAll(prefixes);
 
-        if (existingDatabases.isEmpty()) {
-            // None of the databases exist, empty query.
+        if (existingPrefixes.isEmpty()) {
+            // None of the prefixes exist, empty query.
             return false;
         }
 
@@ -812,33 +834,32 @@
         List<String> namespaceFilters = searchSpecBuilder.getNamespaceFiltersList();
         searchSpecBuilder.clearNamespaceFilters();
 
-        // Rewrite filters to include a database prefix.
-        for (String databaseName : existingDatabases) {
-            Set<String> existingSchemaTypes = mSchemaMapLocked.get(databaseName);
-            String databaseNamePrefix = getDatabasePrefix(databaseName);
+        // Rewrite filters to include a prefix.
+        for (String prefix : existingPrefixes) {
+            Set<String> existingSchemaTypes = mSchemaMapLocked.get(prefix);
             if (schemaTypeFilters.isEmpty()) {
                 // Include all schema types
                 searchSpecBuilder.addAllSchemaTypeFilters(existingSchemaTypes);
             } else {
-                // Qualify the given schema types
+                // Add the prefix to the given schema types
                 for (int i = 0; i < schemaTypeFilters.size(); i++) {
-                    String qualifiedType = databaseNamePrefix + schemaTypeFilters.get(i);
-                    if (existingSchemaTypes.contains(qualifiedType)) {
-                        searchSpecBuilder.addSchemaTypeFilters(qualifiedType);
+                    String prefixedType = prefix + schemaTypeFilters.get(i);
+                    if (existingSchemaTypes.contains(prefixedType)) {
+                        searchSpecBuilder.addSchemaTypeFilters(prefixedType);
                     }
                 }
             }
 
-            Set<String> existingNamespaces = mNamespaceMapLocked.get(databaseName);
+            Set<String> existingNamespaces = mNamespaceMapLocked.get(prefix);
             if (namespaceFilters.isEmpty()) {
                 // Include all namespaces
                 searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
             } else {
-                // Qualify the given namespaces.
+                // Prefix the given namespaces.
                 for (int i = 0; i < namespaceFilters.size(); i++) {
-                    String qualifiedNamespace = databaseNamePrefix + namespaceFilters.get(i);
-                    if (existingNamespaces.contains(qualifiedNamespace)) {
-                        searchSpecBuilder.addNamespaceFilters(qualifiedNamespace);
+                    String prefixedNamespace = prefix + namespaceFilters.get(i);
+                    if (existingNamespaces.contains(prefixedNamespace)) {
+                        searchSpecBuilder.addNamespaceFilters(prefixedNamespace);
                     }
                 }
             }
@@ -857,36 +878,41 @@
         return schemaProto.getSchema();
     }
 
-    /** Returns true if {@code databaseName} has a {@code schemaType} */
+    /**
+     * Returns true if the {@code packageName} and {@code databaseName} has the {@code schemaType}
+     */
     @GuardedBy("mReadWriteLock")
-    boolean hasSchemaTypeLocked(@NonNull String databaseName, @NonNull String schemaType) {
+    boolean hasSchemaTypeLocked(
+            @NonNull String packageName, @NonNull String databaseName, @NonNull String schemaType) {
+        Preconditions.checkNotNull(packageName);
         Preconditions.checkNotNull(databaseName);
         Preconditions.checkNotNull(schemaType);
 
-        Set<String> schemaTypes = mSchemaMapLocked.get(databaseName);
+        String prefix = createPrefix(packageName, databaseName);
+        Set<String> schemaTypes = mSchemaMapLocked.get(prefix);
         if (schemaTypes == null) {
             return false;
         }
 
-        return schemaTypes.contains(getDatabasePrefix(databaseName) + schemaType);
+        return schemaTypes.contains(prefix + schemaType);
     }
 
-    /** Returns a set of all databases AppSearchImpl knows about. */
+    /** Returns a set of all prefixes AppSearchImpl knows about. */
     @GuardedBy("mReadWriteLock")
     @NonNull
-    Set<String> getDatabasesLocked() {
+    Set<String> getPrefixesLocked() {
         return mSchemaMapLocked.keySet();
     }
 
     @NonNull
-    private static String getDatabasePrefix(@NonNull String databaseName) {
-        // TODO(b/170370381): Reconsider the way we separate database names for security reasons.
-        return databaseName + DATABASE_DELIMITER;
+    static String createPrefix(@NonNull String packageName, @NonNull String databaseName) {
+        return packageName + PACKAGE_DELIMITER + databaseName + DATABASE_DELIMITER;
     }
 
     @NonNull
-    private static String removeDatabasePrefix(@NonNull String prefixedString)
-            throws AppSearchException {
+    private static String removePrefix(@NonNull String prefixedString) throws AppSearchException {
+        // The prefix is made up of the package, then the database. So we only need to find the
+        // database cutoff.
         int delimiterIndex;
         if ((delimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER)) != -1) {
             // Add 1 to include the char size of the DATABASE_DELIMITER
@@ -898,22 +924,24 @@
     }
 
     @NonNull
-    private static String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException {
-        int delimiterIndex = prefixedValue.indexOf(DATABASE_DELIMITER);
-        if (delimiterIndex == -1) {
+    private static String getPrefix(@NonNull String prefixedString) throws AppSearchException {
+        int databaseDelimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER);
+        if (databaseDelimiterIndex == -1) {
             throw new AppSearchException(
                     AppSearchResult.RESULT_UNKNOWN_ERROR,
                     "The databaseName prefixed value doesn't contains a valid database name.");
         }
-        return prefixedValue.substring(0, delimiterIndex);
+
+        // Add 1 to include the char size of the DATABASE_DELIMITER
+        return prefixedString.substring(0, databaseDelimiterIndex + 1);
     }
 
     private static void addToMap(
-            Map<String, Set<String>> map, String databaseName, String prefixedValue) {
-        Set<String> values = map.get(databaseName);
+            Map<String, Set<String>> map, String prefix, String prefixedValue) {
+        Set<String> values = map.get(prefix);
         if (values == null) {
             values = new ArraySet<>();
-            map.put(databaseName, values);
+            map.put(prefix, values);
         }
         values.add(prefixedValue);
     }
@@ -994,7 +1022,7 @@
                 SearchResultProto.ResultProto.Builder resultBuilder =
                         searchResultProto.getResults(i).toBuilder();
                 DocumentProto.Builder documentBuilder = resultBuilder.getDocument().toBuilder();
-                removeDatabasesFromDocument(documentBuilder);
+                removePrefixesFromDocument(documentBuilder);
                 resultBuilder.setDocument(documentBuilder);
                 resultsBuilder.setResults(i, resultBuilder);
             }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
index 0b68ebc..411da2f 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
@@ -51,24 +51,58 @@
  * this class. Take care to not cause any circular dependencies.
  */
 class VisibilityStore {
-    // Schema type for documents that hold AppSearch's metadata, e.g. visibility settings
+    /** Schema type for documents that hold AppSearch's metadata, e.g. visibility settings */
     @VisibleForTesting static final String SCHEMA_TYPE = "Visibility";
 
-    // Property that holds the list of platform-hidden schemas, as part of the visibility
-    // settings.
+    /**
+     * Property that holds the list of platform-hidden schemas, as part of the visibility settings.
+     */
     @VisibleForTesting
     static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
-    // Database name to prefix all visibility schemas and documents with. Special-cased to
-    // minimize the chance of collision with a client-supplied database.
 
-    @VisibleForTesting static final String DATABASE_NAME = "$$__AppSearch__Database";
+    /** Schema for the VisibilityStore's docuemnts. */
+    @VisibleForTesting
+    static final AppSearchSchema SCHEMA =
+            new AppSearchSchema.Builder(SCHEMA_TYPE)
+                    .addProperty(
+                            new AppSearchSchema.PropertyConfig.Builder(
+                                            NOT_PLATFORM_SURFACEABLE_PROPERTY)
+                                    .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+                                    .setCardinality(
+                                            AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+                                    .build())
+                    .build();
 
-    // Namespace of documents that contain visibility settings
-    private static final String NAMESPACE = "namespace";
+    /**
+     * These cannot have any of the special characters used by AppSearchImpl (e.g. {@link
+     * AppSearchImpl#PACKAGE_DELIMITER} or {@link AppSearchImpl#DATABASE_DELIMITER}.
+     */
+    static final String PACKAGE_NAME = "VS#Pkg";
+
+    static final String DATABASE_NAME = "VS#Db";
+
+    /**
+     * Prefix that AppSearchImpl creates for the VisibilityStore based on our package name and
+     * database name. Tracked here to tell when we're looking at our own prefix when looking through
+     * AppSearchImpl.
+     */
+    private static final String VISIBILITY_STORE_PREFIX =
+            AppSearchImpl.createPrefix(PACKAGE_NAME, DATABASE_NAME);
+
+    /** Namespace of documents that contain visibility settings */
+    private static final String NAMESPACE = GenericDocument.DEFAULT_NAMESPACE;
+
+    /**
+     * Prefix to add to all visibility document uri's. IcingSearchEngine doesn't allow empty uri's.
+     */
+    private static final String URI_PREFIX = "uri:";
+
     private final AppSearchImpl mAppSearchImpl;
 
-    // The map contains schemas that are platform-hidden for each database. All schemas in the map
-    // have a database name prefix.
+    /**
+     * Maps prefixes to the set of schemas that are platform-hidden within that prefix. All schemas
+     * in the map are prefixed.
+     */
     private final Map<String, Set<String>> mNotPlatformSurfaceableMap = new ArrayMap<>();
 
     /**
@@ -92,42 +126,36 @@
      * @throws AppSearchException AppSearchException on AppSearchImpl error.
      */
     public void initialize() throws AppSearchException {
-        if (!mAppSearchImpl.hasSchemaTypeLocked(DATABASE_NAME, SCHEMA_TYPE)) {
+        if (!mAppSearchImpl.hasSchemaTypeLocked(PACKAGE_NAME, DATABASE_NAME, SCHEMA_TYPE)) {
             // Schema type doesn't exist yet. Add it.
             mAppSearchImpl.setSchema(
+                    PACKAGE_NAME,
                     DATABASE_NAME,
-                    Collections.singletonList(
-                            new AppSearchSchema.Builder(SCHEMA_TYPE)
-                                    .addProperty(
-                                            new AppSearchSchema.PropertyConfig.Builder(
-                                                            NOT_PLATFORM_SURFACEABLE_PROPERTY)
-                                                    .setDataType(
-                                                            AppSearchSchema.PropertyConfig
-                                                                    .DATA_TYPE_STRING)
-                                                    .setCardinality(
-                                                            AppSearchSchema.PropertyConfig
-                                                                    .CARDINALITY_REPEATED)
-                                                    .build())
-                                    .build()),
+                    Collections.singletonList(SCHEMA),
                     /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                     /*forceOverride=*/ false);
         }
 
-        // Populate visibility settings map
-        for (String database : mAppSearchImpl.getDatabasesLocked()) {
-            if (database.equals(DATABASE_NAME)) {
-                // Our own database. Skip
+        // Populate visibility settings set
+        mNotPlatformSurfaceableMap.clear();
+        for (String prefix : mAppSearchImpl.getPrefixesLocked()) {
+            if (prefix.equals(VISIBILITY_STORE_PREFIX)) {
+                // Our own prefix. Skip
                 continue;
             }
 
             try {
-                // Note: We use the other clients' database names as uris
+                // Note: We use the other clients' prefixed names as uris
                 GenericDocument document =
-                        mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ database);
+                        mAppSearchImpl.getDocument(
+                                PACKAGE_NAME,
+                                DATABASE_NAME,
+                                NAMESPACE,
+                                /*uri=*/ addUriPrefix(prefix));
 
                 String[] schemas =
                         document.getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
-                mNotPlatformSurfaceableMap.put(database, new ArraySet<>(Arrays.asList(schemas)));
+                mNotPlatformSurfaceableMap.put(prefix, new ArraySet<>(Arrays.asList(schemas)));
             } catch (AppSearchException e) {
                 if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
                     // TODO(b/172068212): This indicates some desync error. We were expecting a
@@ -142,51 +170,46 @@
     }
 
     /**
-     * Sets visibility settings for {@code databaseName}. Any previous visibility settings will be
+     * Sets visibility settings for {@code prefix}. Any previous visibility settings will be
      * overwritten.
      *
-     * @param databaseName Database name that owns the {@code schemasNotPlatformSurfaceable}.
-     * @param schemasNotPlatformSurfaceable Set of database-qualified schemas that should be hidden
-     *     from the platform.
+     * @param prefix Prefix that identifies who owns the {@code schemasNotPlatformSurfaceable}.
+     * @param schemasNotPlatformSurfaceable Set of prefixed schemas that should be hidden from the
+     *     platform.
      * @throws AppSearchException on AppSearchImpl error.
      */
     public void setVisibility(
-            @NonNull String databaseName, @NonNull Set<String> schemasNotPlatformSurfaceable)
+            @NonNull String prefix, @NonNull Set<String> schemasNotPlatformSurfaceable)
             throws AppSearchException {
-        Preconditions.checkNotNull(databaseName);
+        Preconditions.checkNotNull(prefix);
         Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
 
         // Persist the document
         GenericDocument.Builder visibilityDocument =
-                new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
+                new GenericDocument.Builder(/*uri=*/ addUriPrefix(prefix), SCHEMA_TYPE)
                         .setNamespace(NAMESPACE);
         if (!schemasNotPlatformSurfaceable.isEmpty()) {
             visibilityDocument.setPropertyString(
                     NOT_PLATFORM_SURFACEABLE_PROPERTY,
                     schemasNotPlatformSurfaceable.toArray(new String[0]));
         }
-        mAppSearchImpl.putDocument(DATABASE_NAME, visibilityDocument.build());
+        mAppSearchImpl.putDocument(PACKAGE_NAME, DATABASE_NAME, visibilityDocument.build());
 
         // Update derived data structures.
-        mNotPlatformSurfaceableMap.put(databaseName, schemasNotPlatformSurfaceable);
+        mNotPlatformSurfaceableMap.put(prefix, schemasNotPlatformSurfaceable);
     }
 
-    /**
-     * Returns the set of database-qualified schemas in {@code databaseName} that are hidden from
-     * the platform.
-     *
-     * @param databaseName Database name to retrieve schemas for
-     * @return Set of database-qualified schemas that are hidden from the platform. Empty set if
-     *     none exist.
-     */
+    /** Returns if the schema is surfaceable by the platform. */
     @NonNull
-    public Set<String> getSchemasNotPlatformSurfaceable(@NonNull String databaseName) {
-        Preconditions.checkNotNull(databaseName);
-        Set<String> schemasNotPlatformSurfaceable = mNotPlatformSurfaceableMap.get(databaseName);
-        if (schemasNotPlatformSurfaceable == null) {
-            return Collections.emptySet();
+    public boolean isSchemaPlatformSurfaceable(
+            @NonNull String prefix, @NonNull String prefixedSchema) {
+        Preconditions.checkNotNull(prefix);
+        Preconditions.checkNotNull(prefixedSchema);
+        Set<String> notPlatformSurfaceableSchemas = mNotPlatformSurfaceableMap.get(prefix);
+        if (notPlatformSurfaceableSchemas == null) {
+            return true;
         }
-        return schemasNotPlatformSurfaceable;
+        return !notPlatformSurfaceableSchemas.contains(prefixedSchema);
     }
 
     /**
@@ -199,4 +222,14 @@
         mNotPlatformSurfaceableMap.clear();
         initialize();
     }
+
+    /**
+     * Adds a uri prefix to create a visibility store document's uri.
+     *
+     * @param uri Non-prefixed uri
+     * @return Prefixed uri
+     */
+    private static String addUriPrefix(String uri) {
+        return URI_PREFIX + uri;
+    }
 }
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 57c48d8..5a7ab1d 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-If5fd2bd705d5507d044706701a94b2e1496ef1df
+Ia04e81bb574831fa7e8a26c725e53133b39ee3ef
diff --git a/core/api/current.txt b/core/api/current.txt
index 92d5298..e658591 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6023,7 +6023,7 @@
 
   public class NotificationManager {
     method public String addAutomaticZenRule(android.app.AutomaticZenRule);
-    method public boolean areBubblesAllowed();
+    method @Deprecated public boolean areBubblesAllowed();
     method public boolean areNotificationsEnabled();
     method public boolean areNotificationsPaused();
     method public boolean canNotifyAsPackage(@NonNull String);
@@ -6040,6 +6040,7 @@
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
     method public android.app.AutomaticZenRule getAutomaticZenRule(String);
     method public java.util.Map<java.lang.String,android.app.AutomaticZenRule> getAutomaticZenRules();
+    method public int getBubblePreference();
     method @NonNull public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy();
     method public final int getCurrentInterruptionFilter();
     method public int getImportance();
@@ -6074,6 +6075,9 @@
     field public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1; // 0x1
     field public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3; // 0x3
     field public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1; // 0xffffffff
+    field public static final int BUBBLE_PREFERENCE_ALL = 1; // 0x1
+    field public static final int BUBBLE_PREFERENCE_NONE = 0; // 0x0
+    field public static final int BUBBLE_PREFERENCE_SELECTED = 2; // 0x2
     field public static final String EXTRA_AUTOMATIC_RULE_ID = "android.app.extra.AUTOMATIC_RULE_ID";
     field public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID = "android.app.extra.AUTOMATIC_ZEN_RULE_ID";
     field public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS = "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS";
@@ -10242,6 +10246,7 @@
     field public static final String ALARM_SERVICE = "alarm";
     field public static final String APPWIDGET_SERVICE = "appwidget";
     field public static final String APP_OPS_SERVICE = "appops";
+    field public static final String APP_SEARCH_SERVICE = "app_search";
     field public static final String AUDIO_SERVICE = "audio";
     field public static final String BATTERY_SERVICE = "batterymanager";
     field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
@@ -15727,7 +15732,7 @@
     method public boolean setPosition(@NonNull android.graphics.Rect);
     method public boolean setProjectBackwards(boolean);
     method public boolean setProjectionReceiver(boolean);
-    method public void setRenderEffect(@Nullable android.graphics.RenderEffect);
+    method public boolean setRenderEffect(@Nullable android.graphics.RenderEffect);
     method public boolean setRotationX(float);
     method public boolean setRotationY(float);
     method public boolean setRotationZ(float);
@@ -31548,6 +31553,7 @@
     method @Nullable public java.io.File getDirectory();
     method @Nullable public String getMediaStoreVolumeName();
     method public String getState();
+    method @Nullable public java.util.UUID getStorageUuid();
     method @Nullable public String getUuid();
     method public boolean isEmulated();
     method public boolean isPrimary();
@@ -48446,6 +48452,7 @@
     method public void setPivotY(float);
     method public void setPointerIcon(android.view.PointerIcon);
     method public void setPressed(boolean);
+    method public void setRenderEffect(@Nullable android.graphics.RenderEffect);
     method public final void setRevealOnFocusHint(boolean);
     method public final void setRight(int);
     method public void setRotation(float);
@@ -57915,6 +57922,7 @@
     method public int getModifiers();
     method @NonNull public String getName();
     method @Nullable public Package getPackage();
+    method @NonNull public String getPackageName();
     method @Nullable public java.security.ProtectionDomain getProtectionDomain();
     method @Nullable public java.net.URL getResource(@NonNull String);
     method @Nullable public java.io.InputStream getResourceAsStream(@NonNull String);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 821d3f1..6085fac 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1344,6 +1344,7 @@
 
   public abstract class RoleControllerService extends android.app.Service {
     ctor public RoleControllerService();
+    method @NonNull public android.app.role.RolePrivileges getRolePrivileges(@NonNull String);
     method @WorkerThread public abstract boolean onAddRoleHolder(@NonNull String, @NonNull String, int);
     method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
     method @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int);
@@ -1370,6 +1371,18 @@
     field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
   }
 
+  public final class RolePrivileges implements android.os.Parcelable {
+    ctor public RolePrivileges(@NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>);
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getAppOpPermissions();
+    method @NonNull public java.util.List<java.lang.String> getAppOps();
+    method @NonNull public java.util.List<java.lang.String> getCapabilities();
+    method @NonNull public java.util.List<java.lang.String> getPermissions();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final String CAPABILITY_NOTIFICATION_LISTENER = "android.app.role.capability.NOTIFICATION_LISTENER";
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.role.RolePrivileges> CREATOR;
+  }
+
 }
 
 package android.app.time {
@@ -6955,6 +6968,19 @@
     method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
   }
 
+  public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+    ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
+    field public final int ipTos;
+    field public final int ipTtl;
+    field public final int tcpAck;
+    field public final int tcpSeq;
+    field public final int tcpWindow;
+    field public final int tcpWindowScale;
+  }
+
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
@@ -8466,6 +8492,7 @@
     field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
     field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
     field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+    field public static final String NAMESPACE_OTA = "ota";
     field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
     field public static final String NAMESPACE_PERMISSIONS = "permissions";
     field public static final String NAMESPACE_PRIVACY = "privacy";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ffe2736f..1998563 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2440,7 +2440,6 @@
   }
 
   public class DisplayAreaOrganizer extends android.window.WindowOrganizer {
-    ctor public DisplayAreaOrganizer();
     method public void onDisplayAreaAppeared(@NonNull android.window.DisplayAreaInfo, @NonNull android.view.SurfaceControl);
     method public void onDisplayAreaVanished(@NonNull android.window.DisplayAreaInfo);
     method @CallSuper @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.window.DisplayAreaAppearedInfo> registerOrganizer(int);
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index b27d9cd..bc7f4d6 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -33,6 +33,7 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 import java.util.HashMap;
@@ -56,6 +57,9 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        getWindow().addSystemFlags(
+                android.view.WindowManager.LayoutParams
+                        .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
         mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
         mAccountManagerResponse =
                 getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java
index e3352bc..63e005f 100644
--- a/core/java/android/accounts/ChooseAccountTypeActivity.java
+++ b/core/java/android/accounts/ChooseAccountTypeActivity.java
@@ -31,6 +31,7 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 import java.util.ArrayList;
@@ -51,6 +52,9 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        getWindow().addSystemFlags(
+                android.view.WindowManager.LayoutParams
+                        .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "ChooseAccountTypeActivity.onCreate(savedInstanceState="
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index a2464d5..2be88ab 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -15,8 +15,6 @@
  */
 package android.accounts;
 
-import com.google.android.collect.Sets;
-
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
@@ -35,6 +33,8 @@
 
 import com.android.internal.R;
 
+import com.google.android.collect.Sets;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -139,6 +139,9 @@
             Log.v(TAG, "ChooseTypeAndAccountActivity.onCreate(savedInstanceState="
                     + savedInstanceState + ")");
         }
+        getWindow().addSystemFlags(
+                android.view.WindowManager.LayoutParams
+                        .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
         mCallingUid = getLaunchedFromUid();
         mCallingPackage = getLaunchedFromPackage();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d8cb7a6..294a363 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7098,7 +7098,7 @@
         if (getWindow() != null &&
                 getWindow().peekDecorView() != null &&
                 getWindow().peekDecorView().getViewRootImpl() != null) {
-            getWindow().peekDecorView().getViewRootImpl().dump(prefix, fd, writer, args);
+            getWindow().peekDecorView().getViewRootImpl().dump(prefix, writer);
         }
 
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0b0781e..a2b9157 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1878,7 +1878,7 @@
         /** Launched from recents gesture handler. */
         public static final int TYPE_RECENTS_ANIMATION = 4;
 
-        @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+        @IntDef(prefix = { "TYPE_" }, value = {
                 TYPE_LAUNCHER,
                 TYPE_NOTIFICATION,
                 TYPE_LOCKSCREEN,
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1009f66..20953c6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1169,9 +1169,18 @@
     public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
             AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER;
 
+    /**
+     * App output audio is being recorded
+     *
+     * @hide
+     */
+    // TODO: Add as AppProtoEnums
+    public static final int OP_RECORD_AUDIO_OUTPUT = 106;
+
+
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public static final int _NUM_OP = 106;
+    public static final int _NUM_OP = 107;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1537,6 +1546,12 @@
     @TestApi
     public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
             "android:use_icc_auth_with_device_identifier";
+    /**
+     * App output audio is being recorded
+     *
+     * @hide
+     */
+    public static final String OPSTR_RECORD_AUDIO_OUTPUT = "android:record_audio_output";
 
     /** {@link #sAppOpsToNote} not initialized yet for this op */
     private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@@ -1735,6 +1750,7 @@
             OP_MANAGE_ONGOING_CALLS,            // MANAGE_ONGOING_CALLS
             OP_MANAGE_CREDENTIALS,              // MANAGE_CREDENTIALS
             OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            OP_RECORD_AUDIO_OUTPUT,             // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -1847,6 +1863,7 @@
             OPSTR_MANAGE_ONGOING_CALLS,
             OPSTR_MANAGE_CREDENTIALS,
             OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+            OPSTR_RECORD_AUDIO_OUTPUT,
     };
 
     /**
@@ -1960,6 +1977,7 @@
             "MANAGE_ONGOING_CALLS",
             "MANAGE_CREDENTIALS",
             "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
+            "RECORD_AUDIO_OUTPUT",
     };
 
     /**
@@ -2074,6 +2092,7 @@
             Manifest.permission.MANAGE_ONGOING_CALLS,
             null, // no permission for OP_MANAGE_CREDENTIALS
             Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+            null, // no permission for OP_RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2188,6 +2207,7 @@
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
             null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            null, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2301,6 +2321,7 @@
             null, // MANAGE_ONGOING_CALLS
             null, // MANAGE_CREDENTIALS
             null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            null, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2413,6 +2434,7 @@
             AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
             AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
             AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
     };
 
     /**
@@ -2529,6 +2551,7 @@
             true, // MANAGE_ONGOING_CALLS
             false, // MANAGE_CREDENTIALS
             true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+            false, // RECORD_AUDIO_OUTPUT
     };
 
     /**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 82f61a4..c528588 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5163,16 +5163,10 @@
             bindHeaderChronometerAndTime(contentView, p, hasTextToLeft);
             bindProfileBadge(contentView, p);
             bindAlertedIcon(contentView, p);
-            bindFeedbackIcon(contentView, p);
             bindExpandButton(contentView, p);
             mN.mUsesStandardHeader = true;
         }
 
-        private void bindFeedbackIcon(RemoteViews contentView, StandardTemplateParams p) {
-            int color = getNeutralColor(p);
-            contentView.setDrawableTint(R.id.feedback, false, color, PorterDuff.Mode.SRC_ATOP);
-        }
-
         private void bindExpandButton(RemoteViews contentView, StandardTemplateParams p) {
             int color = isColorized(p) ? getPrimaryTextColor(p) : getSecondaryTextColor(p);
             contentView.setDrawableTint(R.id.expand_button, false, color,
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index da7a29f..58f382d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -34,6 +34,7 @@
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -532,15 +533,23 @@
     public static final int IMPORTANCE_MAX = 5;
 
     /**
-     * @hide
+     * Indicates that the no bubbles are allowed from the app. If the app sends bubbles, only the
+     * notification will appear. The notification will have an affordance allowing the user to
+     * bubble it. If the user selects this affordance, that notification is approved to bubble
+     * and the apps' bubble preference will be upgraded to {@link #BUBBLE_PREFERENCE_SELECTED}.
      */
     public static final int BUBBLE_PREFERENCE_NONE = 0;
+
     /**
-     * @hide
+     * Indicates that all bubbles are allowed from the app. If the app sends bubbles, the bubble
+     * will appear along with the notification.
      */
     public static final int BUBBLE_PREFERENCE_ALL = 1;
+
     /**
-     * @hide
+     * Indicates that only notifications selected by the user will appear as bubbles. If
+     * the app sends bubbles that haven't been selected, only the notification appear. If the
+     * bubble has been approved by the user, it will appear along with the notification.
      */
     public static final int BUBBLE_PREFERENCE_SELECTED = 2;
 
@@ -1323,10 +1332,12 @@
      * notification shade, floating over other apps' content.
      *
      * <p>This value will be ignored for notifications that are posted to channels that do not
-     * allow bubbles ({@link NotificationChannel#canBubble()}.
+     * allow bubbles ({@link NotificationChannel#canBubble()}).
      *
      * @see Notification#getBubbleMetadata()
+     * @deprecated use {@link #getBubblePreference()} instead.
      */
+    @Deprecated
     public boolean areBubblesAllowed() {
         INotificationManager service = getService();
         try {
@@ -1337,6 +1348,34 @@
     }
 
     /**
+     * Gets the bubble preference for the app. This preference only applies to notifications that
+     * have been properly configured to bubble.
+     *
+     * <p>
+     * If {@link #BUBBLE_PREFERENCE_ALL}, then any bubble notification will appear as a bubble, as
+     * long as the user hasn't excluded it ({@link NotificationChannel#canBubble()}).
+     *
+     * <p>
+     * If {@link #BUBBLE_PREFERENCE_SELECTED}, then any bubble notification will appear as a bubble,
+     * as long as the user has selected it.
+     *
+     * <p>
+     * If {@link #BUBBLE_PREFERENCE_NONE}, then no notification may appear as a bubble from the app.
+     *
+     * @see Notification#getBubbleMetadata()
+     * @return the users' bubble preference for the app.
+     */
+    public int getBubblePreference() {
+        INotificationManager service = getService();
+        try {
+            return service.getBubblePreferenceForPackage(mContext.getPackageName(),
+                    Binder.getCallingUid());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Silences the current notification sound, if ones currently playing.
      * <p>
      * It is intended to handle use-cases such as silencing a ringing call
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index abdd537..06ad9c9 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -15,22 +15,18 @@
 # Notification
 per-file *Notification* = file:/packages/SystemUI/OWNERS
 
-#Wallpaper
-per-file Wallpaper*.java = file:/core/java/android/service/wallpaper/OWNERS
-per-file IWallpaper*.aidl = file:/core/java/android/service/wallpaper/OWNERS
+# ResourcesManager
+per-file ResourcesManager = rtmitchell@google.com, toddke@google.com
+
+# Wallpaper
+per-file *Wallpaper* = file:/core/java/android/service/wallpaper/OWNERS
 
 # WindowManager
-per-file Activity*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Activity*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *Activity* = file:/services/core/java/com/android/server/wm/OWNERS
 per-file ClientTransactionHandler.java = file:/services/core/java/com/android/server/wm/OWNERS
 per-file Fragment.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file IActivity*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file IAppTask.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file ITaskStackListener.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file LocalActivityManager.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Task*.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Window*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS
 
 # TODO(b/174932174): determine the ownership of KeyguardManager.java
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index a6bf4ddd..5326bf3 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -117,7 +117,6 @@
 import android.media.tv.tunerresourcemanager.TunerResourceManager;
 import android.net.ConnectivityDiagnosticsManager;
 import android.net.ConnectivityManager;
-import android.net.ConnectivityThread;
 import android.net.EthernetManager;
 import android.net.IConnectivityManager;
 import android.net.IEthernetManager;
@@ -781,8 +780,7 @@
             public LowpanManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                 IBinder b = ServiceManager.getServiceOrThrow(Context.LOWPAN_SERVICE);
                 ILowpanManager service = ILowpanManager.Stub.asInterface(b);
-                return new LowpanManager(ctx.getOuterContext(), service,
-                        ConnectivityThread.getInstanceLooper());
+                return new LowpanManager(ctx.getOuterContext(), service);
             }});
 
         registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 94084b85..2a79c72 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2056,7 +2056,9 @@
     /**
      * Result code for {@link #checkProvisioningPreCondition}.
      *
-     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user.
+     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_USER} if the user is a system user and
+     * for {@link #ACTION_PROVISION_MANAGED_DEVICE} on devices running headless system user mode
+     * and the user is a system user.
      *
      * @hide
      */
@@ -12675,4 +12677,21 @@
             }
         }
     }
+
+    // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+    /**
+     * Used by ManagedProvisioning app to factory reset the device when DO cannto be provisioned.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MASTER_CLEAR)
+    public void factoryReset(String reason) {
+        if (mService != null) {
+            try {
+                mService.factoryReset(reason);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index c02fcab..b046014 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -231,7 +231,13 @@
      * Returns the profile owner component for the given user, or {@code null} if there is not one.
      */
     @Nullable
-    public abstract ComponentName getProfileOwnerAsUser(int userHandle);
+    public abstract ComponentName getProfileOwnerAsUser(@UserIdInt int userId);
+
+    /**
+     * Returns the user id of the device owner, or {@link UserHandle#USER_NULL} if there is not one.
+     */
+    @UserIdInt
+    public abstract int getDeviceOwnerUserId();
 
     /**
      * Returns whether the given package is a device owner or a profile owner in the calling user.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index bcc90f7..a81b506 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -488,4 +488,6 @@
     boolean canProfileOwnerResetPasswordWhenLocked(int userId);
 
     void setNextOperationSafety(int operation, boolean safe);
+    // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+    void factoryReset(String reason);
 }
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index e870597..f60e42f 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -28,7 +28,6 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.service.notification.StatusBarNotification;
 
 /**
  * The People Space tile contains all relevant information to render a tile in People Space: namely
@@ -48,7 +47,10 @@
     private long mLastInteractionTimestamp;
     private boolean mIsImportantConversation;
     private boolean mIsHiddenConversation;
-    private StatusBarNotification mNotification;
+    private String mNotificationKey;
+    // TODO: add mNotificationTimestamp
+    private CharSequence mNotificationContent;
+    private Uri mNotificationDataUri;
     private Intent mIntent;
     // TODO: add a List of the Status objects once created
 
@@ -62,7 +64,9 @@
         mLastInteractionTimestamp = b.mLastInteractionTimestamp;
         mIsImportantConversation = b.mIsImportantConversation;
         mIsHiddenConversation = b.mIsHiddenConversation;
-        mNotification = b.mNotification;
+        mNotificationKey = b.mNotificationKey;
+        mNotificationContent = b.mNotificationContent;
+        mNotificationDataUri = b.mNotificationDataUri;
         mIntent = b.mIntent;
     }
 
@@ -112,10 +116,18 @@
 
     /**
      * If a notification is currently active that maps to the relevant shortcut ID, provides the
-     * {@link StatusBarNotification} associated.
+     * associated notification's key.
      */
-    public StatusBarNotification getNotification() {
-        return mNotification;
+    public String getNotificationKey() {
+        return mNotificationKey;
+    }
+
+    public CharSequence getNotificationContent() {
+        return mNotificationContent;
+    }
+
+    public Uri getNotificationDataUri() {
+        return mNotificationDataUri;
     }
 
     /**
@@ -129,6 +141,22 @@
         return mIntent;
     }
 
+    /** Converts a {@link PeopleSpaceTile} into a {@link PeopleSpaceTile.Builder}. */
+    public PeopleSpaceTile.Builder toBuilder() {
+        PeopleSpaceTile.Builder builder =
+                new PeopleSpaceTile.Builder(mId, mUserName.toString(), mUserIcon, mIntent);
+        builder.setContactUri(mContactUri);
+        builder.setUid(mUid);
+        builder.setPackageName(mPackageName);
+        builder.setLastInteractionTimestamp(mLastInteractionTimestamp);
+        builder.setIsImportantConversation(mIsImportantConversation);
+        builder.setIsHiddenConversation(mIsHiddenConversation);
+        builder.setNotificationKey(mNotificationKey);
+        builder.setNotificationContent(mNotificationContent);
+        builder.setNotificationDataUri(mNotificationDataUri);
+        return builder;
+    }
+
     /** Builder to create a {@link PeopleSpaceTile}. */
     public static class Builder {
         private String mId;
@@ -140,7 +168,9 @@
         private long mLastInteractionTimestamp;
         private boolean mIsImportantConversation;
         private boolean mIsHiddenConversation;
-        private StatusBarNotification mNotification;
+        private String mNotificationKey;
+        private CharSequence mNotificationContent;
+        private Uri mNotificationDataUri;
         private Intent mIntent;
 
         /** Builder for use only if a shortcut is not available for the tile. */
@@ -214,9 +244,21 @@
             return this;
         }
 
-        /** Sets the associated notification. */
-        public Builder setNotification(StatusBarNotification notification) {
-            mNotification = notification;
+        /** Sets the associated notification's key. */
+        public Builder setNotificationKey(String notificationKey) {
+            mNotificationKey = notificationKey;
+            return this;
+        }
+
+        /** Sets the associated notification's content. */
+        public Builder setNotificationContent(CharSequence notificationContent) {
+            mNotificationContent = notificationContent;
+            return this;
+        }
+
+        /** Sets the associated notification's data URI. */
+        public Builder setNotificationDataUri(Uri notificationDataUri) {
+            mNotificationDataUri = notificationDataUri;
             return this;
         }
 
@@ -242,7 +284,9 @@
         mLastInteractionTimestamp = in.readLong();
         mIsImportantConversation = in.readBoolean();
         mIsHiddenConversation = in.readBoolean();
-        mNotification = in.readParcelable(StatusBarNotification.class.getClassLoader());
+        mNotificationKey = in.readString();
+        mNotificationContent = in.readCharSequence();
+        mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
         mIntent = in.readParcelable(Intent.class.getClassLoader());
     }
 
@@ -259,9 +303,11 @@
         dest.writeInt(mUid);
         dest.writeString(mPackageName);
         dest.writeLong(mLastInteractionTimestamp);
-        dest.writeParcelable(mNotification, flags);
         dest.writeBoolean(mIsImportantConversation);
         dest.writeBoolean(mIsHiddenConversation);
+        dest.writeString(mNotificationKey);
+        dest.writeCharSequence(mNotificationContent);
+        dest.writeParcelable(mNotificationDataUri, flags);
         dest.writeParcelable(mIntent, flags);
     }
 
diff --git a/core/java/android/app/role/IRoleController.aidl b/core/java/android/app/role/IRoleController.aidl
index 8a43d7f..fbf79a4 100644
--- a/core/java/android/app/role/IRoleController.aidl
+++ b/core/java/android/app/role/IRoleController.aidl
@@ -16,7 +16,9 @@
 
 package android.app.role;
 
+import android.app.role.RolePrivileges;
 import android.os.RemoteCallback;
+import com.android.internal.infra.AndroidFuture;
 
 /**
  * @hide
@@ -40,4 +42,6 @@
             in RemoteCallback callback);
 
     void isRoleVisible(in String roleName, in RemoteCallback callback);
+
+    void getRolePrivileges(in String roleName, in AndroidFuture<RolePrivileges> callback);
 }
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
index d92c956..4c6aa8d 100644
--- a/core/java/android/app/role/RoleControllerService.java
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -16,6 +16,8 @@
 
 package android.app.role;
 
+import static java.util.Collections.emptyList;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -32,6 +34,7 @@
 import android.os.RemoteCallback;
 import android.os.UserHandle;
 
+import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
 
@@ -177,6 +180,20 @@
                 boolean visible = onIsRoleVisible(roleName);
                 callback.sendResult(visible ? Bundle.EMPTY : null);
             }
+
+            @Override
+            public void getRolePrivileges(String roleName, AndroidFuture<RolePrivileges> callback) {
+                enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
+
+                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+                Objects.requireNonNull(callback, "callback cannot be null");
+
+                try {
+                    callback.complete(RoleControllerService.this.getRolePrivileges(roleName));
+                } catch (Throwable t) {
+                    callback.completeExceptionally(t);
+                }
+            }
         };
     }
 
@@ -302,4 +319,14 @@
      * @return whether the role should be visible to user
      */
     public abstract boolean onIsRoleVisible(@NonNull String roleName);
+
+    /**
+     * Queries the {@link RolePrivileges privileges} that the given role grants.
+     *
+     * @param roleName name of the role to quey for
+     * @return the {@link RolePrivileges} for the role
+     */
+    public @NonNull RolePrivileges getRolePrivileges(@NonNull String roleName) {
+        return new RolePrivileges(emptyList(), emptyList(), emptyList(), emptyList());
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/core/java/android/app/role/RolePrivileges.aidl
similarity index 63%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
copy to core/java/android/app/role/RolePrivileges.aidl
index 23d86a0..1561ad4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/core/java/android/app/role/RolePrivileges.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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,12 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
 
-/**
- * Class to hold state of divider that needs to persist across configuration changes.
- */
-final class DividerState {
-    public boolean animateAfterRecentsDrawn;
-    public float mRatioPositionBeforeMinimized;
-}
+package android.app.role;
+
+parcelable RolePrivileges;
diff --git a/core/java/android/app/role/RolePrivileges.java b/core/java/android/app/role/RolePrivileges.java
new file mode 100644
index 0000000..5fc0b0a08
--- /dev/null
+++ b/core/java/android/app/role/RolePrivileges.java
@@ -0,0 +1,221 @@
+/*
+ * 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.role;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+
+/**
+ * Describes a set of privileges granted by a {@link RoleManager role}
+ *
+ * @hide
+ */
+@SystemApi
+@DataClass
+public final class RolePrivileges implements Parcelable {
+
+    /**
+     * An identifier of a role holder app being granted the
+     * {@link android.service.notification.NotificationListenerService Notification Access}
+     * privilege.
+     */
+    public static final String CAPABILITY_NOTIFICATION_LISTENER =
+            "android.app.role.capability.NOTIFICATION_LISTENER";
+
+    /**
+     * Permissions granted to the role holder(s).
+     */
+    private @NonNull List<String> mPermissions;
+    /**
+     * Appop permissions granted to the role holder(s).
+     */
+    private @NonNull List<String> mAppOpPermissions;
+    /**
+     * Appops granted to the role holder(s).
+     */
+    private @NonNull List<String> mAppOps;
+    /**
+     * Special access granted to the role holder(s).
+     *
+     * @see #CAPABILITY_NOTIFICATION_LISTENER
+     */
+    private @NonNull List<String> mCapabilities;
+
+
+
+    // Code below generated by codegen v1.0.22.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/role/RolePrivileges.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new RolePrivileges.
+     *
+     * @param permissions
+     *   Permissions granted to the role holder(s).
+     * @param appOpPermissions
+     *   Appop permissions granted to the role holder(s).
+     * @param appOps
+     *   Appops granted to the role holder(s).
+     * @param capabilities
+     *   Special access granted to the role holder(s).
+     */
+    @DataClass.Generated.Member
+    public RolePrivileges(
+            @NonNull List<String> permissions,
+            @NonNull List<String> appOpPermissions,
+            @NonNull List<String> appOps,
+            @NonNull List<String> capabilities) {
+        this.mPermissions = permissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPermissions);
+        this.mAppOpPermissions = appOpPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAppOpPermissions);
+        this.mAppOps = appOps;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAppOps);
+        this.mCapabilities = capabilities;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mCapabilities);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Permissions granted to the role holder(s).
+     */
+    @DataClass.Generated.Member
+    public @NonNull List<String> getPermissions() {
+        return mPermissions;
+    }
+
+    /**
+     * Appop permissions granted to the role holder(s).
+     */
+    @DataClass.Generated.Member
+    public @NonNull List<String> getAppOpPermissions() {
+        return mAppOpPermissions;
+    }
+
+    /**
+     * Appops granted to the role holder(s).
+     */
+    @DataClass.Generated.Member
+    public @NonNull List<String> getAppOps() {
+        return mAppOps;
+    }
+
+    /**
+     * Special access granted to the role holder(s).
+     *
+     * @see #CAPABILITY_NOTIFICATION_LISTENER
+     */
+    @DataClass.Generated.Member
+    public @NonNull List<String> getCapabilities() {
+        return mCapabilities;
+    }
+
+    @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.writeStringList(mPermissions);
+        dest.writeStringList(mAppOpPermissions);
+        dest.writeStringList(mAppOps);
+        dest.writeStringList(mCapabilities);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ RolePrivileges(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        List<String> permissions = new java.util.ArrayList<>();
+        in.readStringList(permissions);
+        List<String> appOpPermissions = new java.util.ArrayList<>();
+        in.readStringList(appOpPermissions);
+        List<String> appOps = new java.util.ArrayList<>();
+        in.readStringList(appOps);
+        List<String> capabilities = new java.util.ArrayList<>();
+        in.readStringList(capabilities);
+
+        this.mPermissions = permissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mPermissions);
+        this.mAppOpPermissions = appOpPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAppOpPermissions);
+        this.mAppOps = appOps;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAppOps);
+        this.mCapabilities = capabilities;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mCapabilities);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<RolePrivileges> CREATOR
+            = new Parcelable.Creator<RolePrivileges>() {
+        @Override
+        public RolePrivileges[] newArray(int size) {
+            return new RolePrivileges[size];
+        }
+
+        @Override
+        public RolePrivileges createFromParcel(@NonNull android.os.Parcel in) {
+            return new RolePrivileges(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1607546429137L,
+            codegenVersion = "1.0.22",
+            sourceFile = "frameworks/base/core/java/android/app/role/RolePrivileges.java",
+            inputSignatures = "public static final  java.lang.String CAPABILITY_NOTIFICATION_LISTENER\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOpPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOps\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mCapabilities\nclass RolePrivileges extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f3e1a87..58e8886 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5225,7 +5225,6 @@
      * indexing and querying app data managed by the system.
      *
      * @see #getSystemService(String)
-     * @hide
      */
     public static final String APP_SEARCH_SERVICE = "app_search";
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 4347f99..01d4c280 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -53,10 +53,12 @@
 import android.os.UserHandle;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.ExceptionUtils;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.Closeable;
@@ -1349,12 +1351,13 @@
          *
          * @throws PackageManager.NameNotFoundException if the new owner could not be found.
          * @throws SecurityException if called after the session has been committed or abandoned.
-         * @throws IllegalArgumentException if streams opened through
+         * @throws IllegalStateException if streams opened through
          *                                  {@link #openWrite(String, long, long) are still open.
+         * @throws IllegalArgumentException if {@code packageName} is invalid.
          */
         public void transfer(@NonNull String packageName)
                 throws PackageManager.NameNotFoundException {
-            Objects.requireNonNull(packageName);
+            Preconditions.checkArgument(!TextUtils.isEmpty(packageName));
 
             try {
                 mSession.transfer(packageName);
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ae10f40..3a73de6 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -350,7 +350,7 @@
      *
      * @hide
      */
-    public static final int HDMI_CEC_VERSION_1_4_b = 0x05;
+    public static final int HDMI_CEC_VERSION_1_4_B = 0x05;
     /**
      * Version constant for HDMI-CEC v2.0.
      *
@@ -361,7 +361,7 @@
      * @hide
      */
     @IntDef({
-            HDMI_CEC_VERSION_1_4_b,
+            HDMI_CEC_VERSION_1_4_B,
             HDMI_CEC_VERSION_2_0
     })
     @Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index a8cafef..c0b177d 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -203,7 +203,7 @@
     public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
             int vendorId, String displayName, int powerStatus) {
         this(logicalAddress, physicalAddress, portId, deviceType,
-                vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     /**
@@ -221,7 +221,7 @@
             int vendorId, String displayName) {
         this(logicalAddress, physicalAddress, portId, deviceType,
                 vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     /**
@@ -239,7 +239,7 @@
         mId = idForHardware(portId);
         mLogicalAddress = -1;
         mDeviceType = DEVICE_RESERVED;
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mVendorId = 0;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "HDMI" + portId;
@@ -265,7 +265,7 @@
         mId = idForMhlDevice(portId);
         mLogicalAddress = -1;
         mDeviceType = DEVICE_RESERVED;
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mVendorId = 0;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "Mobile";
@@ -287,7 +287,7 @@
 
         mLogicalAddress = -1;
         mDeviceType = DEVICE_INACTIVE;
-        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+        mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mPortId = PORT_INVALID;
         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
         mDisplayName = "Inactive";
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3f2c966..09c3050 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2108,17 +2108,6 @@
         // ignored
     }
 
-    /** {@hide} */
-    @Deprecated
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
-        try {
-            return mService.getActiveNetworkQuotaInfo();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
     /**
      * @hide
      * @deprecated Talk to TelephonyManager directly
@@ -3163,9 +3152,9 @@
     }
 
     /**
-     * Set sign in error notification to visible or in visible
+     * Set sign in error notification to visible or invisible
      *
-     * {@hide}
+     * @hide
      * @deprecated Doesn't properly deal with multiple connected networks of the same type.
      */
     @Deprecated
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 4173200..fb01283 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -25,7 +25,6 @@
 import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
-import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkState;
 import android.net.ISocketKeepaliveCallback;
@@ -76,7 +75,6 @@
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     NetworkState[] getAllNetworkState();
 
-    NetworkQuotaInfo getActiveNetworkQuotaInfo();
     boolean isActiveNetworkMetered();
 
     boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress,
diff --git a/core/java/android/net/TcpKeepalivePacketData.java b/core/java/android/net/TcpKeepalivePacketData.java
new file mode 100644
index 0000000..ddb3a6a7
--- /dev/null
+++ b/core/java/android/net/TcpKeepalivePacketData.java
@@ -0,0 +1,163 @@
+/*
+ * 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.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.InetAddress;
+import java.util.Objects;
+
+/**
+ * Represents the actual tcp keep alive packets which will be used for hardware offload.
+ * @hide
+ */
+@SystemApi
+public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
+    private static final String TAG = "TcpKeepalivePacketData";
+
+    /** TCP sequence number. */
+    public final int tcpSeq;
+
+    /** TCP ACK number. */
+    public final int tcpAck;
+
+    /** TCP RCV window. */
+    public final int tcpWindow;
+
+    /** TCP RCV window scale. */
+    public final int tcpWindowScale;
+
+    /** IP TOS. */
+    public final int ipTos;
+
+    /** IP TTL. */
+    public final int ipTtl;
+
+    public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
+            @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data,
+            int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl)
+            throws InvalidPacketException {
+        super(srcAddress, srcPort, dstAddress, dstPort, data);
+        this.tcpSeq = tcpSeq;
+        this.tcpAck = tcpAck;
+        this.tcpWindow = tcpWindow;
+        this.tcpWindowScale = tcpWindowScale;
+        this.ipTos = ipTos;
+        this.ipTtl = ipTtl;
+    }
+
+    @Override
+    public boolean equals(@Nullable final Object o) {
+        if (!(o instanceof TcpKeepalivePacketData)) return false;
+        final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
+        final InetAddress srcAddress = getSrcAddress();
+        final InetAddress dstAddress = getDstAddress();
+        return srcAddress.equals(other.getSrcAddress())
+                && dstAddress.equals(other.getDstAddress())
+                && getSrcPort() == other.getSrcPort()
+                && getDstPort() == other.getDstPort()
+                && this.tcpAck == other.tcpAck
+                && this.tcpSeq == other.tcpSeq
+                && this.tcpWindow == other.tcpWindow
+                && this.tcpWindowScale == other.tcpWindowScale
+                && this.ipTos == other.ipTos
+                && this.ipTtl == other.ipTtl;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
+                tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl);
+    }
+
+    /**
+     * Parcelable Implementation.
+     * Note that this object implements parcelable (and needs to keep doing this as it inherits
+     * from a class that does), but should usually be parceled as a stable parcelable using
+     * the toStableParcelable() and fromStableParcelable() methods.
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Write to parcel. */
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeString(getSrcAddress().getHostAddress());
+        out.writeString(getDstAddress().getHostAddress());
+        out.writeInt(getSrcPort());
+        out.writeInt(getDstPort());
+        out.writeByteArray(getPacket());
+        out.writeInt(tcpSeq);
+        out.writeInt(tcpAck);
+        out.writeInt(tcpWindow);
+        out.writeInt(tcpWindowScale);
+        out.writeInt(ipTos);
+        out.writeInt(ipTtl);
+    }
+
+    private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
+        InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
+        InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
+        int srcPort = in.readInt();
+        int dstPort = in.readInt();
+        byte[] packet = in.createByteArray();
+        int tcpSeq = in.readInt();
+        int tcpAck = in.readInt();
+        int tcpWnd = in.readInt();
+        int tcpWndScale = in.readInt();
+        int ipTos = in.readInt();
+        int ipTtl = in.readInt();
+        return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
+                tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
+    }
+
+    /** Parcelable Creator. */
+    public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
+            new Parcelable.Creator<TcpKeepalivePacketData>() {
+                public TcpKeepalivePacketData createFromParcel(Parcel in) {
+                    try {
+                        return readFromParcel(in);
+                    } catch (InvalidPacketException e) {
+                        throw new IllegalArgumentException(
+                                "Invalid TCP keepalive data: " + e.getError());
+                    }
+                }
+
+                public TcpKeepalivePacketData[] newArray(int size) {
+                    return new TcpKeepalivePacketData[size];
+                }
+            };
+
+    @Override
+    public String toString() {
+        return "saddr: " + getSrcAddress()
+                + " daddr: " + getDstAddress()
+                + " sport: " + getSrcPort()
+                + " dport: " + getDstPort()
+                + " seq: " + tcpSeq
+                + " ack: " + tcpAck
+                + " window: " + tcpWindow
+                + " windowScale: " + tcpWindowScale
+                + " tos: " + ipTos
+                + " ttl: " + ipTtl;
+    }
+}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 74880b2..3956ef9 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -42,9 +42,10 @@
     public static @interface PowerComponent {
     }
 
-    public static final int POWER_COMPONENT_CPU = 0;
+    public static final int POWER_COMPONENT_USAGE = 0;
+    public static final int POWER_COMPONENT_CPU = 1;
 
-    public static final int POWER_COMPONENT_COUNT = 1;
+    public static final int POWER_COMPONENT_COUNT = 2;
 
     public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
     public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -63,10 +64,11 @@
     public static @interface TimeComponent {
     }
 
-    public static final int TIME_COMPONENT_CPU = 0;
-    public static final int TIME_COMPONENT_CPU_FOREGROUND = 1;
+    public static final int TIME_COMPONENT_USAGE = 0;
+    public static final int TIME_COMPONENT_CPU = 1;
+    public static final int TIME_COMPONENT_CPU_FOREGROUND = 2;
 
-    public static final int TIME_COMPONENT_COUNT = 2;
+    public static final int TIME_COMPONENT_COUNT = 3;
 
     public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
     public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
@@ -131,4 +133,80 @@
     protected void writeToParcel(Parcel dest, int flags) {
         mPowerComponents.writeToParcel(dest, flags);
     }
+
+    protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
+        final PowerComponents.Builder mPowerComponentsBuilder;
+
+        public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) {
+            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
+                    customTimeComponentCount);
+        }
+
+        /**
+         * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
+         *
+         * @param componentId    The ID of the power component, e.g.
+         *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+         * @param componentPower Amount of consumed power in mAh.
+         */
+        @SuppressWarnings("unchecked")
+        @NonNull
+        public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
+            mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
+            return (T) this;
+        }
+
+        /**
+         * Sets the amount of drain attributed to the specified custom drain type.
+         *
+         * @param componentId    The ID of the custom power component.
+         * @param componentPower Amount of consumed power in mAh.
+         */
+        @SuppressWarnings("unchecked")
+        @NonNull
+        public T setConsumedPowerForCustomComponent(int componentId, double componentPower) {
+            mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower);
+            return (T) this;
+        }
+
+        /**
+         * Sets the total amount of power consumed since BatteryStats reset, mAh.
+         */
+        @SuppressWarnings("unchecked")
+        @NonNull
+        public T setConsumedPower(double consumedPower) {
+            mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower);
+            return (T) this;
+        }
+
+        /**
+         * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
+         *
+         * @param componentId              The ID of the time component, e.g.
+         *                                 {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
+         * @param componentUsageTimeMillis Amount of time in microseconds.
+         */
+        @SuppressWarnings("unchecked")
+        @NonNull
+        public T setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
+                long componentUsageTimeMillis) {
+            mPowerComponentsBuilder.setUsageDurationMillis(componentId, componentUsageTimeMillis);
+            return (T) this;
+        }
+
+        /**
+         * Sets the amount of time used by the specified custom component.
+         *
+         * @param componentId              The ID of the custom power component.
+         * @param componentUsageTimeMillis Amount of time in microseconds.
+         */
+        @SuppressWarnings("unchecked")
+        @NonNull
+        public T setUsageDurationForCustomComponentMillis(int componentId,
+                long componentUsageTimeMillis) {
+            mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
+                    componentUsageTimeMillis);
+            return (T) this;
+        }
+    }
 }
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 79f58f6..af8e8de 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
+import android.util.SparseArray;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -31,14 +32,20 @@
     private final double mConsumedPower;
     private final int mDischargePercentage;
     private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
+    private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
 
     private BatteryUsageStats(@NonNull Builder builder) {
         mConsumedPower = builder.mConsumedPower;
         mDischargePercentage = builder.mDischargePercentage;
-        final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
+        int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
         mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
         for (int i = 0; i < uidBatteryConsumerCount; i++) {
-            mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.get(i).build());
+            mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.valueAt(i).build());
+        }
+        int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
+        mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount);
+        for (int i = 0; i < systemBatteryConsumerCount; i++) {
+            mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build());
         }
     }
 
@@ -63,6 +70,11 @@
         return mUidBatteryConsumers;
     }
 
+    @NonNull
+    public List<SystemBatteryConsumer> getSystemBatteryConsumers() {
+        return mSystemBatteryConsumers;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -71,6 +83,8 @@
     private BatteryUsageStats(@NonNull Parcel source) {
         mUidBatteryConsumers = new ArrayList<>();
         source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
+        mSystemBatteryConsumers = new ArrayList<>();
+        source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
         mConsumedPower = source.readDouble();
         mDischargePercentage = source.readInt();
     }
@@ -78,6 +92,7 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeParcelableList(mUidBatteryConsumers, flags);
+        dest.writeParcelableList(mSystemBatteryConsumers, flags);
         dest.writeDouble(mConsumedPower);
         dest.writeInt(mDischargePercentage);
     }
@@ -97,10 +112,19 @@
      * Builder for BatteryUsageStats.
      */
     public static final class Builder {
+        private final int mCustomPowerComponentCount;
+        private final int mCustomTimeComponentCount;
         private double mConsumedPower;
         private int mDischargePercentage;
-        private final ArrayList<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
-                new ArrayList<>();
+        private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
+                new SparseArray<>();
+        private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
+                new SparseArray<>();
+
+        public Builder(int customPowerComponentCount, int customTimeComponentCount) {
+            mCustomPowerComponentCount = customPowerComponentCount;
+            mCustomTimeComponentCount = customTimeComponentCount;
+        }
 
         /**
          * Constructs a read-only object using the Builder values.
@@ -113,6 +137,7 @@
         /**
          * Sets the battery discharge amount since BatteryStats reset as percentage of the full
          * charge.
+         *
          */
         @SuppressLint("PercentageInt") // See b/174188159
         @NonNull
@@ -131,18 +156,40 @@
         }
 
         /**
-         * Adds a UidBatteryConsumer, which represents battery attribution data for an
-         * individual UID.
+         * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
+         * data for an individual UID.
          */
         @NonNull
-        public Builder addUidBatteryConsumerBuilder(
-                @NonNull UidBatteryConsumer.Builder uidBatteryConsumer) {
-            mUidBatteryConsumerBuilders.add(uidBatteryConsumer);
-            return this;
+        public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder(
+                @NonNull BatteryStats.Uid batteryStatsUid) {
+            int uid = batteryStatsUid.getUid();
+            UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
+            if (builder == null) {
+                builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount,
+                        mCustomTimeComponentCount, batteryStatsUid);
+                mUidBatteryConsumerBuilders.put(uid, builder);
+            }
+            return builder;
+        }
+
+        /**
+         * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
+         * data for an individual UID.
+         */
+        @NonNull
+        public SystemBatteryConsumer.Builder getOrCreateSystemBatteryConsumerBuilder(
+                @SystemBatteryConsumer.DrainType int drainType) {
+            SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType);
+            if (builder == null) {
+                builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount,
+                        mCustomTimeComponentCount, drainType);
+                mSystemBatteryConsumerBuilders.put(drainType, builder);
+            }
+            return builder;
         }
 
         @NonNull
-        public List<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
+        public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
             return mUidBatteryConsumerBuilders;
         }
     }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 379d6e6..92fe98c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1436,9 +1436,7 @@
     public static FileDescriptor convertToModernFd(FileDescriptor fd) {
         try {
             Context context = AppGlobals.getInitialApplication();
-            // TODO(b/169327180): Consider device config.
-            if (!SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", false)
-                    || !SystemProperties.getBoolean("persist.sys.fuse.transcode_optimize", true)
+            if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
                     || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
                 // If transcode is enabled we optimize by default, unless explicitly disabled.
                 // Never convert modern fd for MediaProvider, because this requires
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 3b334a7..49451d9 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -29,3 +29,6 @@
 per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS
 per-file *Telephony* = file:/telephony/OWNERS
 per-file *Zygote* = file:/ZYGOTE_OWNERS
+
+# RecoverySystem
+per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
new file mode 100644
index 0000000..570a2dc
--- /dev/null
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Contains power consumption data attributed to a system-wide drain type.
+ *
+ * {@hide}
+ */
+public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable {
+
+    //                           ****************
+    // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto)
+    // so the constant values must never change.
+    //                           ****************
+    @IntDef(prefix = {"DRAIN_TYPE_"}, value = {
+            DRAIN_TYPE_AMBIENT_DISPLAY,
+            // Reserved: APP
+            DRAIN_TYPE_BLUETOOTH,
+            DRAIN_TYPE_CAMERA,
+            DRAIN_TYPE_CELL,
+            DRAIN_TYPE_FLASHLIGHT,
+            DRAIN_TYPE_IDLE,
+            DRAIN_TYPE_MEMORY,
+            DRAIN_TYPE_OVERCOUNTED,
+            DRAIN_TYPE_PHONE,
+            DRAIN_TYPE_SCREEN,
+            DRAIN_TYPE_UNACCOUNTED,
+            // Reserved: USER,
+            DRAIN_TYPE_WIFI,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public static @interface DrainType {
+    }
+
+    public static final int DRAIN_TYPE_AMBIENT_DISPLAY = 0;
+    public static final int DRAIN_TYPE_BLUETOOTH = 2;
+    public static final int DRAIN_TYPE_CAMERA = 3;
+    public static final int DRAIN_TYPE_CELL = 4;
+    public static final int DRAIN_TYPE_FLASHLIGHT = 5;
+    public static final int DRAIN_TYPE_IDLE = 6;
+    public static final int DRAIN_TYPE_MEMORY = 7;
+    public static final int DRAIN_TYPE_OVERCOUNTED = 8;
+    public static final int DRAIN_TYPE_PHONE = 9;
+    public static final int DRAIN_TYPE_SCREEN = 10;
+    public static final int DRAIN_TYPE_UNACCOUNTED = 11;
+    public static final int DRAIN_TYPE_WIFI = 13;
+
+    @DrainType
+    private final int mDrainType;
+
+    @DrainType
+    public int getDrainType() {
+        return mDrainType;
+    }
+
+    private SystemBatteryConsumer(@NonNull SystemBatteryConsumer.Builder builder) {
+        super(builder.mPowerComponentsBuilder.build());
+        mDrainType = builder.mDrainType;
+    }
+
+    private SystemBatteryConsumer(Parcel in) {
+        super(new PowerComponents(in));
+        mDrainType = in.readInt();
+    }
+
+    /**
+     * Writes the contents into a Parcel.
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(mDrainType);
+    }
+
+    public static final Creator<SystemBatteryConsumer> CREATOR =
+            new Creator<SystemBatteryConsumer>() {
+                @Override
+                public SystemBatteryConsumer createFromParcel(Parcel in) {
+                    return new SystemBatteryConsumer(in);
+                }
+
+                @Override
+                public SystemBatteryConsumer[] newArray(int size) {
+                    return new SystemBatteryConsumer[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Builder for SystemBatteryConsumer.
+     */
+    public static final class Builder extends BaseBuilder<Builder> {
+        @DrainType
+        private final int mDrainType;
+
+        Builder(int customPowerComponentCount, int customTimeComponentCount,
+                @DrainType int drainType) {
+            super(customPowerComponentCount, customTimeComponentCount);
+            mDrainType = drainType;
+        }
+
+        /**
+         * Creates a read-only object out of the Builder values.
+         */
+        @NonNull
+        public SystemBatteryConsumer build() {
+            return new SystemBatteryConsumer(this);
+        }
+    }
+}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index d12ccb5..06cf4a6 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -80,16 +80,14 @@
     /**
      * Builder for UidBatteryConsumer.
      */
-    public static final class Builder {
-        private final PowerComponents.Builder mPowerComponentsBuilder;
+    public static final class Builder extends BaseBuilder<Builder> {
         private final BatteryStats.Uid mBatteryStatsUid;
         private final int mUid;
         private String mPackageWithHighestDrain;
 
         public Builder(int customPowerComponentCount, int customTimeComponentCount,
                 BatteryStats.Uid batteryStatsUid) {
-            mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
-                    customTimeComponentCount);
+            super(customPowerComponentCount, customTimeComponentCount);
             mBatteryStatsUid = batteryStatsUid;
             mUid = batteryStatsUid.getUid();
         }
@@ -111,69 +109,6 @@
         }
 
         /**
-         * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
-         *
-         * @param componentId    The ID of the power component, e.g.
-         *                       {@link BatteryConsumer#POWER_COMPONENT_CPU}.
-         * @param componentPower Amount of consumed power in mAh.
-         */
-        @NonNull
-        public Builder setConsumedPower(@PowerComponent int componentId, double componentPower) {
-            mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
-            return this;
-        }
-
-        /**
-         * Sets the amount of drain attributed to the specified custom drain type.
-         *
-         * @param componentId    The ID of the custom power component.
-         * @param componentPower Amount of consumed power in mAh.
-         */
-        @NonNull
-        public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
-            mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower);
-            return this;
-        }
-
-        /**
-         * Sets the amount of power consumed since BatteryStats reset, mAh.
-         */
-        @NonNull
-        public Builder setConsumedPower(double consumedPower) {
-            mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower);
-            return this;
-        }
-
-        /**
-         * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
-         *
-         * @param componentId                  The ID of the time component, e.g.
-         *                                     {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
-         * @param componentUsageDurationMillis Amount of time in milliseconds.
-         */
-        @NonNull
-        public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
-                long componentUsageDurationMillis) {
-            mPowerComponentsBuilder.setUsageDurationMillis(componentId,
-                    componentUsageDurationMillis);
-            return this;
-        }
-
-        /**
-         * Sets the amount of time used by the specified custom component.
-         *
-         * @param componentId                  The ID of the custom power component.
-         * @param componentUsageDurationMillis Amount of time in milliseconds.
-         */
-        @NonNull
-        public Builder setUsageDurationForCustomComponentMillis(int componentId,
-                long componentUsageDurationMillis) {
-            mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
-                    componentUsageDurationMillis);
-            return this;
-        }
-
-        /**
          * Sets the name of the package owned by this UID that consumed the highest amount
          * of power since BatteryStats reset.
          */
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index a52eecc..8ac1fc1 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -38,6 +38,7 @@
 import java.io.CharArrayWriter;
 import java.io.File;
 import java.util.Locale;
+import java.util.UUID;
 
 /**
  * Information about a shared/external storage volume for a specific user.
@@ -98,6 +99,7 @@
     private final boolean mAllowMassStorage;
     private final long mMaxFileSize;
     private final UserHandle mOwner;
+    private final UUID mUuid;
     private final String mFsUuid;
     private final String mState;
 
@@ -133,7 +135,7 @@
     /** {@hide} */
     public StorageVolume(String id, File path, File internalPath, String description,
             boolean primary, boolean removable, boolean emulated, boolean allowMassStorage,
-            long maxFileSize, UserHandle owner, String fsUuid, String state) {
+            long maxFileSize, UserHandle owner, UUID uuid, String fsUuid, String state) {
         mId = Preconditions.checkNotNull(id);
         mPath = Preconditions.checkNotNull(path);
         mInternalPath = Preconditions.checkNotNull(internalPath);
@@ -144,6 +146,7 @@
         mAllowMassStorage = allowMassStorage;
         mMaxFileSize = maxFileSize;
         mOwner = Preconditions.checkNotNull(owner);
+        mUuid = uuid;
         mFsUuid = fsUuid;
         mState = Preconditions.checkNotNull(state);
     }
@@ -159,6 +162,11 @@
         mAllowMassStorage = in.readInt() != 0;
         mMaxFileSize = in.readLong();
         mOwner = in.readParcelable(null);
+        if (in.readInt() != 0) {
+            mUuid = StorageManager.convert(in.readString());
+        } else {
+            mUuid = null;
+        }
         mFsUuid = in.readString8();
         mState = in.readString8();
     }
@@ -288,6 +296,20 @@
     }
 
     /**
+     * Gets the converted volume UUID. If a valid UUID is returned, it is compatible with other
+     * APIs that make use of {@link UUID} like {@link StorageManager#allocateBytes} and
+     * {@link android.content.pm.ApplicationInfo#storageUuid}
+     *
+     * @return the UUID for the volume or {@code null} for "portable" storage devices which haven't
+     * been adopted.
+     *
+     * @see <a href="https://source.android.com/devices/storage/adoptable">Adoptable storage</a>
+     */
+    public @Nullable UUID getStorageUuid() {
+        return mUuid;
+    }
+
+    /**
      * Gets the volume UUID, if any.
      */
     public @Nullable String getUuid() {
@@ -513,6 +535,12 @@
         parcel.writeInt(mAllowMassStorage ? 1 : 0);
         parcel.writeLong(mMaxFileSize);
         parcel.writeParcelable(mOwner, flags);
+        if (mUuid != null) {
+            parcel.writeInt(1);
+            parcel.writeString8(StorageManager.convert(mUuid));
+        } else {
+            parcel.writeInt(0);
+        }
         parcel.writeString8(mFsUuid);
         parcel.writeString8(mState);
     }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 237a9f2..f57d157 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -45,6 +45,7 @@
 import java.util.Comparator;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * Information about a storage volume that may be mounted. A volume may be a
@@ -401,6 +402,7 @@
         }
 
         String description = null;
+        UUID uuid = null;
         String derivedFsUuid = fsUuid;
         long maxFileSize = 0;
 
@@ -410,7 +412,10 @@
             final VolumeInfo privateVol = storage.findPrivateForEmulated(this);
             if (privateVol != null) {
                 description = storage.getBestVolumeDescription(privateVol);
+                uuid = StorageManager.convert(privateVol.fsUuid);
                 derivedFsUuid = privateVol.fsUuid;
+            } else {
+                uuid = StorageManager.UUID_DEFAULT;
             }
 
             if (isPrimaryEmulatedForUser(userId)) {
@@ -439,7 +444,7 @@
 
         return new StorageVolume(id, userPath, internalPath, description, isPrimary(), removable,
                 emulated, allowMassStorage, maxFileSize, new UserHandle(userId),
-                derivedFsUuid, envState);
+                uuid, derivedFsUuid, envState);
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index ee67ca6..1cc982e7 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -116,7 +116,7 @@
         }
 
         return new StorageVolume(id, userPath, internalPath, description, primary, removable,
-                emulated, allowMassStorage, maxFileSize, user, fsUuid, envState);
+                emulated, allowMassStorage, maxFileSize, user, null /* uuid */, fsUuid, envState);
     }
 
     public void dump(IndentingPrintWriter pw) {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index f58fa15..ec4d81c 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -444,6 +444,14 @@
     public static final String NAMESPACE_PERMISSIONS = "permissions";
 
     /**
+     * Namespace for ota related features.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String NAMESPACE_OTA = "ota";
+
+    /**
      * Namespace for all widget related features.
      *
      * @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index daa17aa..2dbd3ed 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1848,7 +1848,7 @@
 
     /**
      * Activity Action: Show notification bubble settings for a single app.
-     * See {@link NotificationManager#areBubblesAllowed()}.
+     * See {@link NotificationManager#getBubblePreference()}.
      * <p>
      *     Input: {@link #EXTRA_APP_PACKAGE}, the package to display.
      * <p>
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 41b2fb4..b66dd29e 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -116,20 +116,22 @@
     public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
     public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10;
 
-    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 11;
-    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 12;
+    public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 11;
+    public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 12;
+    public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 13;
+    public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 14;
 
-    public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 13;
-    public static final int ITYPE_TOP_DISPLAY_CUTOUT = 14;
-    public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 15;
-    public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 16;
+    public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 15;
+    public static final int ITYPE_TOP_DISPLAY_CUTOUT = 16;
+    public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 17;
+    public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 18;
 
     /** Input method window. */
-    public static final int ITYPE_IME = 17;
+    public static final int ITYPE_IME = 19;
 
     /** Additional system decorations inset type. */
-    public static final int ITYPE_CLIMATE_BAR = 18;
-    public static final int ITYPE_EXTRA_NAVIGATION_BAR = 19;
+    public static final int ITYPE_CLIMATE_BAR = 20;
+    public static final int ITYPE_EXTRA_NAVIGATION_BAR = 21;
 
     static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR;
     public static final int SIZE = LAST_TYPE + 1;
@@ -542,7 +544,9 @@
             case ITYPE_LEFT_GESTURES:
             case ITYPE_RIGHT_GESTURES:
                 return Type.SYSTEM_GESTURES;
+            case ITYPE_LEFT_TAPPABLE_ELEMENT:
             case ITYPE_TOP_TAPPABLE_ELEMENT:
+            case ITYPE_RIGHT_TAPPABLE_ELEMENT:
             case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
                 return Type.TAPPABLE_ELEMENT;
             case ITYPE_LEFT_DISPLAY_CUTOUT:
@@ -615,8 +619,12 @@
                 return "ITYPE_LEFT_MANDATORY_GESTURES";
             case ITYPE_RIGHT_MANDATORY_GESTURES:
                 return "ITYPE_RIGHT_MANDATORY_GESTURES";
+            case ITYPE_LEFT_TAPPABLE_ELEMENT:
+                return "ITYPE_LEFT_TAPPABLE_ELEMENT";
             case ITYPE_TOP_TAPPABLE_ELEMENT:
                 return "ITYPE_TOP_TAPPABLE_ELEMENT";
+            case ITYPE_RIGHT_TAPPABLE_ELEMENT:
+                return "ITYPE_RIGHT_TAPPABLE_ELEMENT";
             case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
                 return "ITYPE_BOTTOM_TAPPABLE_ELEMENT";
             case ITYPE_LEFT_DISPLAY_CUTOUT:
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9943e02..1d1c87d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -73,6 +73,7 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region;
+import android.graphics.RenderEffect;
 import android.graphics.RenderNode;
 import android.graphics.Shader;
 import android.graphics.drawable.ColorDrawable;
@@ -154,6 +155,7 @@
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -21064,6 +21066,21 @@
     }
 
     /**
+     * Configure the {@link android.graphics.RenderEffect} to apply to this View.
+     * This will apply a visual effect to the results of the View before it is drawn. For example if
+     * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, Shader.TileMode)}
+     * is provided, the contents will be drawn in a separate layer, then this layer will be blurred
+     * when this View is drawn.
+     * @param renderEffect to be applied to the View. Passing null clears the previously configured
+     *                     {@link RenderEffect}
+     */
+    public void setRenderEffect(@Nullable RenderEffect renderEffect) {
+        if (mRenderNode.setRenderEffect(renderEffect)) {
+            invalidateViewProperty(true, true);
+        }
+    }
+
+    /**
      * Updates the {@link Paint} object used with the current layer (used only if the current
      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
@@ -29442,6 +29459,16 @@
             }
             return mScrollCaptureInternal;
         }
+
+        public void dump(String prefix, PrintWriter writer) {
+            String innerPrefix = prefix + "  ";
+            writer.println(prefix + "AttachInfo:");
+            writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
+            writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
+            writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
+            writer.println(innerPrefix + "mUnbufferedDispatchRequested="
+                    + mUnbufferedDispatchRequested);
+        }
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 863ee7b..37c18b5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -200,7 +200,6 @@
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.SurfaceCallbackHelper;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
@@ -7687,12 +7686,18 @@
         mImeFocusController.dumpDebug(proto, IME_FOCUS_CONTROLLER);
     }
 
-    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+    /**
+     * Dump information about this ViewRootImpl
+     * @param prefix the prefix that will be prepended to each line of the produced output
+     * @param writer the writer that will receive the resulting text
+     */
+    public void dump(String prefix, PrintWriter writer) {
         String innerPrefix = prefix + "  ";
         writer.println(prefix + "ViewRoot:");
         writer.println(innerPrefix + "mAdded=" + mAdded);
         writer.println(innerPrefix + "mRemoved=" + mRemoved);
         writer.println(innerPrefix + "mStopped=" + mStopped);
+        writer.println(innerPrefix + "mPausedForTransition=" + mPausedForTransition);
         writer.println(innerPrefix + "mConsumeBatchedInputScheduled="
                 + mConsumeBatchedInputScheduled);
         writer.println(innerPrefix + "mConsumeBatchedInputImmediatelyScheduled="
@@ -7707,6 +7712,12 @@
         writer.println(innerPrefix + "mIsAmbientMode="  + mIsAmbientMode);
         writer.println(innerPrefix + "mUnbufferedInputSource="
                 + Integer.toHexString(mUnbufferedInputSource));
+        if (mAttachInfo != null) {
+            writer.print(innerPrefix + "mAttachInfo= ");
+            mAttachInfo.dump(innerPrefix, writer);
+        } else {
+            writer.println(innerPrefix + "mAttachInfo=<null>");
+        }
 
         mFirstInputStage.dump(innerPrefix, writer);
 
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 673073e..149338c 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -126,6 +126,10 @@
         }
     }
 
+    protected void attachToParentSurface(SurfaceControl.Builder b) {
+        b.setParent(mRootSurface);
+    }
+
     /**
      * IWindowSession implementation.
      */
@@ -135,11 +139,11 @@
             DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
             InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
         final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
-                .setParent(mRootSurface)
                 .setFormat(attrs.format)
                 .setBufferSize(getSurfaceWidth(attrs), getSurfaceHeight(attrs))
                 .setName(attrs.getTitle().toString())
                 .setCallsite("WindowlessWindowManager.addToDisplay");
+        attachToParentSurface(b);
         final SurfaceControl sc = b.build();
 
         if (((attrs.inputFeatures &
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 1ac188c..8a1d4a0 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -24,6 +24,7 @@
 import android.view.SurfaceControl;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Interface for WindowManager to delegate control of display areas.
@@ -113,6 +114,24 @@
      */
     public static final int FEATURE_RUNTIME_TASK_CONTAINER_FIRST = FEATURE_VENDOR_LAST + 1;
 
+    // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are
+    // made on the incoming binder call.
+    private final Executor mExecutor;
+
+    /** @hide */
+    public DisplayAreaOrganizer(@NonNull Executor executor) {
+        mExecutor = executor;
+    }
+
+    /**
+     * Gets the executor to run callbacks on.
+     * @hide
+     */
+    @NonNull
+    public Executor getExecutor() {
+        return mExecutor;
+    }
+
     /**
      * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can
      * not be registered by multiple organizers at the same time.
@@ -208,17 +227,20 @@
         @Override
         public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
                 @NonNull SurfaceControl leash) {
-            DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayAreaInfo, leash);
+            mExecutor.execute(
+                    () -> DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayAreaInfo, leash));
         }
 
         @Override
         public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
-            DisplayAreaOrganizer.this.onDisplayAreaVanished(displayAreaInfo);
+            mExecutor.execute(
+                    () -> DisplayAreaOrganizer.this.onDisplayAreaVanished(displayAreaInfo));
         }
 
         @Override
         public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) {
-            DisplayAreaOrganizer.this.onDisplayAreaInfoChanged(displayAreaInfo);
+            mExecutor.execute(
+                    () -> DisplayAreaOrganizer.this.onDisplayAreaInfoChanged(displayAreaInfo));
         }
     };
 
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index 0d16cc4..26af615 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -188,7 +188,7 @@
         }
         Integer rank = mTargetRanks.get(name);
         if (rank == null) {
-            Log.w(TAG, "Score requested for unknown component.");
+            Log.w(TAG, "Score requested for unknown component. Did you call compute yet?");
             return 0f;
         }
         int consecutiveSumOfRanks = (mTargetRanks.size() - 1) * (mTargetRanks.size()) / 2;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 9668c3b..ea458a1 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -827,8 +827,6 @@
                 queryDirectShareTargets(chooserListAdapter, true);
                 return;
             }
-            final List<DisplayResolveInfo> driList =
-                    getDisplayResolveInfos(chooserListAdapter);
             final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
                     new ArrayList<>();
 
@@ -856,7 +854,7 @@
                         new ComponentName(
                                 appTarget.getPackageName(), appTarget.getClassName())));
             }
-            sendShareShortcutInfoList(shareShortcutInfos, driList, resultList,
+            sendShareShortcutInfoList(shareShortcutInfos, chooserListAdapter, resultList,
                     chooserListAdapter.getUserHandle());
         };
     }
@@ -1995,32 +1993,6 @@
         }
     }
 
-    private List<DisplayResolveInfo> getDisplayResolveInfos(ChooserListAdapter adapter) {
-        // Need to keep the original DisplayResolveInfos to be able to reconstruct ServiceResultInfo
-        // and use the old code path. This Ugliness should go away when Sharesheet is refactored.
-        List<DisplayResolveInfo> driList = new ArrayList<>();
-        int targetsToQuery = 0;
-        for (int i = 0, n = adapter.getDisplayResolveInfoCount(); i < n; i++) {
-            final DisplayResolveInfo dri = adapter.getDisplayResolveInfo(i);
-            if (adapter.getScore(dri) == 0) {
-                // A score of 0 means the app hasn't been used in some time;
-                // don't query it as it's not likely to be relevant.
-                continue;
-            }
-            driList.add(dri);
-            targetsToQuery++;
-            // TODO(b/121287224): Do we need this here? (similar to queryTargetServices)
-            if (targetsToQuery >= SHARE_TARGET_QUERY_PACKAGE_LIMIT) {
-                if (DEBUG) {
-                    Log.d(TAG, "queryTargets hit query target limit "
-                            + SHARE_TARGET_QUERY_PACKAGE_LIMIT);
-                }
-                break;
-            }
-        }
-        return driList;
-    }
-
     @VisibleForTesting
     protected void queryDirectShareTargets(
                 ChooserListAdapter adapter, boolean skipAppPredictionService) {
@@ -2038,14 +2010,13 @@
         if (filter == null) {
             return;
         }
-        final List<DisplayResolveInfo> driList = getDisplayResolveInfos(adapter);
 
         AsyncTask.execute(() -> {
             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, userHandle);
+            sendShareShortcutInfoList(resultList, adapter, null, userHandle);
         });
     }
 
@@ -2082,7 +2053,7 @@
 
     private void sendShareShortcutInfoList(
                 List<ShortcutManager.ShareShortcutInfo> resultList,
-                List<DisplayResolveInfo> driList,
+                ChooserListAdapter chooserListAdapter,
                 @Nullable List<AppTarget> appTargets, UserHandle userHandle) {
         if (appTargets != null && appTargets.size() != resultList.size()) {
             throw new RuntimeException("resultList and appTargets must have the same size."
@@ -2108,10 +2079,10 @@
         // for direct share targets. After ShareSheet is refactored we should use the
         // ShareShortcutInfos directly.
         boolean resultMessageSent = false;
-        for (int i = 0; i < driList.size(); i++) {
+        for (int i = 0; i < chooserListAdapter.getDisplayResolveInfoCount(); i++) {
             List<ShortcutManager.ShareShortcutInfo> matchingShortcuts = new ArrayList<>();
             for (int j = 0; j < resultList.size(); j++) {
-                if (driList.get(i).getResolvedComponentName().equals(
+                if (chooserListAdapter.getDisplayResolveInfo(i).getResolvedComponentName().equals(
                             resultList.get(j).getTargetComponent())) {
                     matchingShortcuts.add(resultList.get(j));
                 }
@@ -2126,7 +2097,8 @@
 
             final Message msg = Message.obtain();
             msg.what = ChooserHandler.SHORTCUT_MANAGER_SHARE_TARGET_RESULT;
-            msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null, userHandle);
+            msg.obj = new ServiceResultInfo(chooserListAdapter.getDisplayResolveInfo(i),
+                    chooserTargets, null, userHandle);
             msg.arg1 = shortcutType;
             mChooserHandler.sendMessage(msg);
             resultMessageSent = true;
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index 108ab92..382b49e 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -1 +1,4 @@
 per-file *AppOp* = file:/core/java/android/permission/OWNERS
+per-file *Resolver* = file:/packages/SystemUI/OWNERS
+per-file *Chooser* = file:/packages/SystemUI/OWNERS
+per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
diff --git a/core/java/com/android/internal/app/ProcessMap.java b/core/java/com/android/internal/app/ProcessMap.java
index 719c79b..542b6d0 100644
--- a/core/java/com/android/internal/app/ProcessMap.java
+++ b/core/java/com/android/internal/app/ProcessMap.java
@@ -22,7 +22,7 @@
 public class ProcessMap<E> {
     final ArrayMap<String, SparseArray<E>> mMap
             = new ArrayMap<String, SparseArray<E>>();
-    
+
     public E get(String name, int uid) {
         SparseArray<E> uids = mMap.get(name);
         if (uids == null) return null;
@@ -62,4 +62,6 @@
     public void clear() {
         mMap.clear();
     }
+
+    public void putAll(ProcessMap<E> other) { mMap.putAll(other.mMap); }
 }
diff --git a/core/java/com/android/internal/app/chooser/OWNERS b/core/java/com/android/internal/app/chooser/OWNERS
new file mode 100644
index 0000000..a6f1632
--- /dev/null
+++ b/core/java/com/android/internal/app/chooser/OWNERS
@@ -0,0 +1 @@
+file:/packages/SystemUI/OWNERS
\ No newline at end of file
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 777534e..13358daf 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -47,6 +47,21 @@
      */
     public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";
 
+    /**
+     * Whether the Notification Assistant can change ranking.
+     */
+    public static final String ENABLE_NAS_RANKING = "enable_nas_ranking";
+
+    /**
+     * Whether the Notification Assistant can prioritize notification.
+     */
+    public static final String ENABLE_NAS_PRIORITIZER = "enable_nas_prioritizer";
+
+    /**
+     * Whether to enable feedback UI for Notification Assistant
+     */
+    public static final String ENABLE_NAS_FEEDBACK = "enable_nas_feedback";
+
     // Flags related to screenshot intelligence
 
     /**
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 571ac1b..36514ff 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -51,6 +51,7 @@
     private boolean mCancelled = false;
     private int mTotalFramesCount = 0;
     private int mMissedFramesCount = 0;
+    private int mSfMissedFramesCount = 0;
     private long mMaxFrameTimeNanos = 0;
 
     private Session mSession;
@@ -132,6 +133,8 @@
             mRendererWrapper.removeObserver(mObserver);
 
             // Log the frame stats as counters to make them easily accessible in traces.
+            Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#sfMissedFrames",
+                    mSfMissedFramesCount);
             Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames",
                     mMissedFramesCount);
             Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
@@ -141,7 +144,7 @@
 
             // Trigger perfetto if necessary.
             boolean overMissedFramesThreshold = mTraceThresholdMissedFrames != -1
-                    && mMissedFramesCount >= mTraceThresholdMissedFrames;
+                    && (mMissedFramesCount + mSfMissedFramesCount) >= mTraceThresholdMissedFrames;
             boolean overFrameTimeThreshold = mTraceThresholdFrameTimeMillis != -1
                     && mMaxFrameTimeNanos >= mTraceThresholdFrameTimeMillis * NANOS_IN_MILLISECOND;
             if (overMissedFramesThreshold || overFrameTimeThreshold) {
@@ -153,7 +156,8 @@
                         mSession.getStatsdInteractionType(),
                         mTotalFramesCount,
                         mMissedFramesCount,
-                        mMaxFrameTimeNanos);
+                        mMaxFrameTimeNanos,
+                        mSfMissedFramesCount);
             }
             return;
         }
@@ -168,6 +172,7 @@
             mMaxFrameTimeNanos = Math.max(totalDurationNanos, mMaxFrameTimeNanos);
         }
 
+        // TODO(b/171049584): Also update mSfMissedFramesCount once the data is available.
         if (isJankyFrame) {
             mMissedFramesCount += 1;
         }
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index e1d0a15..b97fdc9 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -23,7 +23,6 @@
 import android.os.BatteryUsageStats;
 import android.os.Bundle;
 import android.os.SystemClock;
-import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.SparseArray;
@@ -110,19 +109,18 @@
         // TODO(b/174186358): read extra power component number from configuration
         final int customPowerComponentCount = 0;
         final int customTimeComponentCount = 0;
-        final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder()
-                .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
-                .setConsumedPower(batteryStatsHelper.getTotalPower());
+        final BatteryUsageStats.Builder batteryUsageStatsBuilder =
+                new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
+                        .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
+                        .setConsumedPower(batteryStatsHelper.getTotalPower());
 
         final List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
         for (int i = 0; i < usageList.size(); i++) {
             final BatterySipper sipper = usageList.get(i);
             if (sipper.drainType == BatterySipper.DrainType.APP) {
-                batteryUsageStatsBuilder.addUidBatteryConsumerBuilder(
-                        new UidBatteryConsumer.Builder(customPowerComponentCount,
-                                customTimeComponentCount, sipper.uidObj)
-                                .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
-                                .setConsumedPower(sipper.sumPower()));
+                batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(sipper.uidObj)
+                        .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
+                        .setConsumedPower(sipper.sumPower());
             }
         }
 
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 732d291..0f0839c 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -114,9 +114,10 @@
             cpuTimeMs = cpuFgTimeMs;
         }
 
-        app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah);
-        app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs);
-        app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, cpuFgTimeMs);
-        app.setPackageWithHighestDrain(packageWithHighestDrain);
+        app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah)
+                .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs)
+                .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND,
+                        cpuFgTimeMs)
+                .setPackageWithHighestDrain(packageWithHighestDrain);
     }
 }
diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java
index b68899e..27f19c0 100644
--- a/core/java/com/android/internal/os/PhonePowerCalculator.java
+++ b/core/java/com/android/internal/os/PhonePowerCalculator.java
@@ -16,7 +16,10 @@
 
 package com.android.internal.os;
 
+import android.os.BatteryConsumer;
 import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.SystemBatteryConsumer;
 import android.os.UserHandle;
 import android.util.SparseArray;
 
@@ -33,6 +36,19 @@
     }
 
     @Override
+    public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+            long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+        long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000;
+        double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+                * phoneOnTimeMs / (60 * 60 * 1000);
+        if (phoneOnPower != 0) {
+            builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_PHONE)
+                    .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, phoneOnPower)
+                    .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, phoneOnTimeMs);
+        }
+    }
+
+    @Override
     public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
             long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
         long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000;
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index a57339b..23f96d9 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -76,10 +76,10 @@
      */
     public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
             long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
-        final List<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+        final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
                 builder.getUidBatteryConsumerBuilders();
         for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
-            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.get(i);
+            final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
             calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, statsType);
         }
     }
diff --git a/core/java/com/android/internal/util/AnnotationValidations.java b/core/java/com/android/internal/util/AnnotationValidations.java
index 2d3b450..cf5e48f 100644
--- a/core/java/com/android/internal/util/AnnotationValidations.java
+++ b/core/java/com/android/internal/util/AnnotationValidations.java
@@ -182,7 +182,7 @@
             Annotation ignored, int value, Object... params) {}
     public static void validate(Class<? extends Annotation> annotation,
             Annotation ignored, int value) {
-        if (("android.annotation".equals(annotation.getPackageName$())
+        if (("android.annotation".equals(annotation.getPackageName())
                 && annotation.getSimpleName().endsWith("Res"))
                 || ColorInt.class.equals(annotation)) {
             if (value < 0) {
@@ -192,7 +192,7 @@
     }
     public static void validate(Class<? extends Annotation> annotation,
             Annotation ignored, long value) {
-        if ("android.annotation".equals(annotation.getPackageName$())
+        if ("android.annotation".equals(annotation.getPackageName())
                 && annotation.getSimpleName().endsWith("Long")) {
             if (value < 0L) {
                 invalid(annotation, value);
diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS
index 99a7686..851d1f3 100644
--- a/core/java/com/android/internal/view/OWNERS
+++ b/core/java/com/android/internal/view/OWNERS
@@ -2,4 +2,19 @@
 
 file:/core/java/android/view/OWNERS
 
-per-file *Input* = file:/services/core/java/com/android/server/inputmethod/OWNERS
\ No newline at end of file
+# Autofill
+per-file IInlineSuggestions*.aidl = file:/core/java/android/service/autofill/OWNERS
+per-file InlineSuggestions*.java = file:/core/java/android/service/autofill/OWNERS
+
+# Ime
+per-file *Input* = file:/services/core/java/com/android/server/inputmethod/OWNERS
+
+# Surface
+per-file *Surface* = file:/graphics/java/android/graphics/OWNERS
+per-file *Surface* = file:/services/core/java/com/android/server/wm/OWNERS
+
+# WindowManager
+per-file AppearanceRegion = file:/services/core/java/com/android/server/wm/OWNERS
+per-file BaseIWIndow.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file RotationPolicy.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file WindowManagerPolicyThread.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 8048298..54b0340 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -20,11 +20,17 @@
 per-file android_graphics_BLASTBufferQueue.cpp = file:/services/core/java/com/android/server/wm/OWNERS
 per-file android_view_Surface* = file:/services/core/java/com/android/server/wm/OWNERS
 
+# Resources
+per-file android_content_res_* = file:/core/java/android/content/res/OWNERS
+per-file android_util_AssetManager* = file:/core/java/android/content/res/OWNERS
+per-file android_util_StringBlock* = file:/core/java/android/content/res/OWNERS
+per-file android_util_XmlBlock* = file:/core/java/android/content/res/OWNERS
+per-file com_android_internal_content_om_OverlayConfig* = file:/core/java/android/content/res/OWNERS
+
 per-file *Zygote* = file:/ZYGOTE_OWNERS
 per-file Android.bp = file:platform/build/soong:/OWNERS
 per-file android_animation_* = file:/core/java/android/animation/OWNERS
 per-file android_app_admin_* = file:/core/java/android/app/admin/OWNERS
-per-file android_content_res_* = file:/core/java/android/content/res/OWNERS
 per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
 per-file android_hardware_Usb* = file:/services/usb/OWNERS
 per-file android_hardware_display_* = file:/core/java/android/hardware/display/OWNERS
diff --git a/core/res/res/drawable/ic_feedback_alerted.xml b/core/res/res/drawable/ic_feedback_alerted.xml
new file mode 100644
index 0000000..550500a
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_alerted.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="16dp"
+        android:height="16dp"
+        android:viewportWidth="16"
+        android:viewportHeight="16">
+    <path
+        android:pathData="M3.3333,5.6667H6V9.6667H10V5.6667H12.6667L8,1L3.3333,5.6667Z"
+        android:fillColor="#EA4335"/>
+    <path
+        android:strokeWidth="1"
+        android:pathData="M2.9798,8.9798L2.1262,9.8333H3.3333H5.5V13.3333V13.8333H6H10H10.5V13.3333V9.8333H12.6667H13.8738L13.0202,8.9798L8.3536,4.3131L8,3.9596L7.6465,4.3131L2.9798,8.9798Z"
+        android:fillColor="#EA4335"
+        android:strokeColor="#ffffff"/>
+</vector>
diff --git a/core/res/res/drawable/ic_feedback_downrank.xml b/core/res/res/drawable/ic_feedback_downrank.xml
new file mode 100644
index 0000000..c48505e
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_downrank.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="16dp"
+        android:height="16dp"
+        android:viewportWidth="16"
+        android:viewportHeight="16">
+    <path
+        android:pathData="M12.6667,8H10V4H6V8H3.3333L8,12.6667L12.6667,8Z"
+        android:fillColor="#4285F4"/>
+</vector>
diff --git a/core/res/res/drawable/ic_feedback_silenced.xml b/core/res/res/drawable/ic_feedback_silenced.xml
new file mode 100644
index 0000000..aa221b2
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_silenced.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="16dp"
+        android:height="16dp"
+        android:viewportWidth="16"
+        android:viewportHeight="16">
+    <group>
+        <clip-path
+            android:pathData="M16,16l-16,-0l-0,-16l16,-0z"/>
+        <path
+            android:pathData="M12.6667,10.3333H10V6.3333H6V10.3333H3.3333L8,15L12.6667,10.3333Z"
+            android:fillColor="#4285F4"/>
+        <path
+            android:strokeWidth="1"
+            android:pathData="M13.0202,7.0202L13.8738,6.1667H12.6667H10.5V2.6667L10.5,2.1667H10H6H5.5V2.6667V6.1667H3.3333H2.1262L2.9798,7.0202L7.6464,11.6869L8,12.0405L8.3535,11.6869L13.0202,7.0202Z"
+            android:fillColor="#4285F4"
+            android:strokeColor="#ffffff"/>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_feedback_uprank.xml b/core/res/res/drawable/ic_feedback_uprank.xml
new file mode 100644
index 0000000..340780c
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_uprank.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="16dp"
+        android:height="16dp"
+        android:viewportWidth="16"
+        android:viewportHeight="16">
+    <path
+        android:pathData="M3.3333,8H6V12H10V8H12.6667L8,3.3333L3.3333,8Z"
+        android:fillColor="#EA4335"/>
+</vector>
diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml
index 60507ed..361b7a3 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -112,9 +112,8 @@
         android:id="@+id/feedback"
         android:layout_width="@dimen/notification_feedback_size"
         android:layout_height="@dimen/notification_feedback_size"
-        android:layout_marginStart="6dp"
-        android:layout_marginEnd="6dp"
-        android:baseline="10dp"
+        android:layout_marginStart="4dp"
+        android:layout_marginEnd="4dp"
         android:scaleType="fitCenter"
         android:src="@drawable/ic_feedback_indicator"
         android:background="?android:selectableItemBackgroundBorderless"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d41acda..9f92d72 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Laat die program toe om MMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is kan monitor of uitvee, sonder dat jy dit gesien het."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Stuur seluitsendingboodskappe aan"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Laat die program toe om die seluitsendingmodule te bind om seluitsendingboodskappe aan te stuur wanneer hulle ontvang word. Seluitsendingwaarskuwings word in sommige liggings gelewer om jou oor noodsituasies te waarsku. Kwaadwillige programme kan met die werkverrigting of werking van jou toestel inmeng wanneer \'n noodseluitsending ontvang word."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Bestuur voortgaande oproepe"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Stel \'n program in staat om besonderhede oor voortgaande oproepe op jou toestel te sien, en hierdie oproepe te beheer."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lees seluitsending-boodskappe"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lees ingetekende nuus"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index fe45f9e..dea4aa6 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"መተግበሪያው የኤም.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"የሕዋስ ስርጭት መልዕክቶችን ማስተላለፍ"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"የሕዋስ ስርጭት መልዕክቶች እንደመጡ ለማስተላለፍ መተግበሪያው ከሕዋስ ስርጭት ሞዱሉ ጋር እንዲተሳሰር ያስችለዋል። የሕዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የሕዋስ ስርጭት ሲደርስ ተንኮል-አዘል መተግበሪያዎች በመሣሪያዎ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"በመካሄድ ላይ ያሉ ጥሪዎችን አስተዳድር"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"አንድ መተግበሪያ በመካሄድ ላይ ስላሉ ጥሪዎች ዝርዝሮችን እንዲመለከት ያስችለዋል።"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"የምዝገባ መግቦች አንበብ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 89c4fea..7ad157c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -365,6 +365,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"للسماح للتطبيق بتلقي ومعالجة رسائل الوسائط المتعددة. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها لجهازك أو حذفها بدون عرضها لك."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"إعادة توجيه رسائل البث الخلوي"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"يسمح للتطبيق بالارتباط بوحدة البث الخلوي لإعادة توجيه رسائل البث الخلوي بينما يتم استقبالها. ويتم تسليم تنبيهات البث الخلوي في بعض المواقع لتحذيرك في حالات الطوارئ. ويمكن أن تؤثر التطبيقات الضارة على أداء الجهاز أو تشغيله عندما يتم تلقي بث خلوي في حالات الطوارئ."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"قراءة رسائل بث الخلية"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"قراءة الخلاصات المشتركة"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 7dac9a2..e6ab01a 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ ফৰৱাৰ্ড কৰক"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ লাভ কৰিলে সেইবোৰ ফৰৱাৰ্ড কৰিবলৈ এপ্‌টোক চেল সম্প্ৰচাৰ মডিউলটোৰ সৈতে সংযুক্ত হ\'বলৈ অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিসমূহৰ বিষয়ে সতৰ্ক কৰিবলৈ কিছুমান অৱস্থানত চেল সম্প্ৰচাৰ সতৰ্কবাৰ্তাসমূহ ডেলিভাৰ কৰা হয়। কোনো জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰিলে ক্ষতিকাৰক এপ্‌সমূহে আপোনাৰ ডিভাইচটোৰ কাৰ্যক্ষমতা অথবা কাৰ্যপ্ৰণালীত হস্তক্ষেপ কৰিব পাৰে।"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 9fdc754..763bd2a 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Tətbiqə MMS mesajlarını qəbul və emal üçün imkan verir. Bu o deməkdir ki, bu tətbiq sizə göstərmədən cihazınıza göndərilən mesajları silə bilər."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Şəbəkə yayımı mesajlarını yönləndirin"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tətbiqə şəbəkə yayım mesajlarını əldə edildiyi anda yönləndirmək üçün şəbəkə yayımı moduluna bağlanmaq icazəsi verir. Şəbəkə yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı Sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər fövqəladə şəbəkə yayımı əldə edildiyi zaman cihazın performansına və əməliyyatına müdaxilə edə bilər."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobil yayım mesajlarını oxuyur"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tətbiqə telefonunuz tərəfindən alınmış yayım mesajlarını oxuma icazəsi verir. Telefon yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər təcili mobil yayım qəbul edildiyi zaman telefonunun performansına və əməliyyatına müdaxilə edə bilər."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abunə olunmuş xəbərləri oxuyur"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3be770c..77220b2 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -356,6 +356,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje odlaznim pozivima"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o odlaznim pozivima na uređaju i da kontroliše te pozive."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje prijavljenih fidova"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index fc2849e..d092ad6 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -359,6 +359,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пераадрасоўваць паведамленні сотавай трансляцыі"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дазваляе праграме звязвацца з модулем сотавай трансляцыі, каб пераадрасоўваць атрыманыя там паведамленні. Абвесткі сотавай трансляцыі дасылаюцца ў некаторыя месцы, каб папярэджваць вас пра надзвычайныя сітуацыі. Шкодныя праграмы могуць негатыўна ўплываць на прадукцыйнасць або працу прылады падчас атрымання паведамленняў сотавай трансляцыі пра надзвычайныя сітуацыі."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"чытаць паведамленні базавай станцыі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"чытаць падпісаныя каналы"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a6321f5..c648398 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Разрешава на приложението да получава и обработва MMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Препращане на съобщения с клетъчно излъчване"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Разрешава на приложението да се обвърже с модула за клетъчно излъчване, за да препраща получените съобщения с клетъчно излъчване. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни случаи. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управление на текущите обаждания"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Разрешава на приложението да вижда подробности за текущите обаждания на устройството ви и да ги управлява."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"четене на съобщения с клетъчно излъчване"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"четене на емисиите с абонамент"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 269d2c7..6de7e2d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"অ্যাপ্লিকেশানটিকে MMS মেসেজ প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো মেসেজগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"সেল ব্রডকাস্টের মাধ্যমে মেসেজ ফরওয়ার্ড করুন"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"সেল ব্রডকাস্ট মেসেজ পেলে এটি সেল ব্রডকাস্ট মডিউলের সাথে তা যুক্ত করে যাতে সেই মেসেজ ফরওয়ার্ড করা যায়। আপনাকে জরুরি অবস্থা সম্পর্কে সাবধান করতে কিছু লোকেশনে সেল ব্রডকাস্ট অ্যালার্ট মেসেজ ডেলিভার করা হয়। জরুরি সেল ব্রডকাস্ট পাওয়া গেলে ক্ষতিকারক অ্যাপ আপনার ডিভাইসের পারফর্ম্যান্স ও অপারেশনে বাধা সৃষ্টি করতে পারে।"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"সেল সম্প্রচার মেসেজ পড়ুন"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 6ecad70..53a03a7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -356,6 +356,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Omogućava aplikaciji prijem i obradu MMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka info servisa"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dopušta aplikaciji da se veže za modul info servisa kako bi prosljeđivala poruke info servisa. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informacije o vanrednoj situaciji od info servisa."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje pozivima u toku"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o pozivima u toku na vašem uređaju i da ih kontrolira."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji čitanje poruka info servisa koje je primio vaš uređaj. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informaciju o vanrednoj situaciji od info servisa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje sadržaja na koje ste pretplaćeni"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c72ca74..5ce2ff2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet que l\'aplicació rebi i processi missatges MMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar els missatges de difusió mòbil"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet que l\'aplicació es vinculi al mòdul de difusió mòbil per poder reenviar els missatges de difusió mòbil a mesura que es reben. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rebi una difusió mòbil d\'emergència."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestiona les trucades en curs"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permet que una aplicació vegi els detalls sobre les trucades en curs al dispositiu i que controli aquestes trucades."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"llegir missatges de difusió mòbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet que l\'aplicació llegeixi missatges de difusió mòbil rebuts pel dispositiu. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rep una difusió mòbil d\'emergència."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"llegir els feeds als quals esteu subscrit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 8174a6e..6840e2d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Přesměrování zpráv informačních služeb"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikaci vytvořit vazbu s modulem informačních služeb za účelem přesměrovávání přijatých zpráv informačních služeb. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa probíhajících hovorů"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Umožňuje aplikaci zobrazit podrobnosti o probíhajících hovorech v zařízení a tyto hovory ovládat."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čtení zpráv informačních služeb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čtení zdrojů přihlášených k odběru"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0bd9657..d7ff335 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend Cell Broadcast-meddelelser"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillader, at appen bindes til Cell Broadcast-modulet, så Cell Broadcast-meddelelser kan videresendes, når de modtages. I nogle områder sendes der Cell Broadcast-underretninger for at advare dig om nødsituationer. Ondsindede apps kan forstyrre effektiviteten eller driften af din enhed, når den modtager en Cell Broadcast-meddelelse om en nødsituation."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"læse Cell Broadcast-meddelelser"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillader, at appen læser Cell Broadcast-underretninger, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-underretninger for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af ​din ​enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"læse feeds, jeg abonnerer på"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b51ce5d..41f4f8a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Ermöglicht der App, MMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell-Broadcast-Nachrichten weiterleiten"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ermöglicht der App, sich mit dem Cell-Broadcast-Modul zu verbinden, um empfangene Cell-Broadcast-Nachrichten weiterzuleiten. Cell-Broadcast-Benachrichtigungen können in einigen Ländern oder Regionen gesendet werden, um dich bei Notfallsituationen zu warnen. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell-Broadcast-Notfallbenachrichtigung eingeht."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Cell Broadcast-Nachrichten lesen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ermöglicht der App, von deinem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um dich über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Abonnierte Feeds lesen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a794e48..aa2ee69 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Προώθηση μηνυμάτων εκπομπής κινητής τηλεφωνίας"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Επιτρέπει στην εφαρμογή να συνδέεται στη λειτουργική μονάδα εκπομπής κινητής τηλεφωνίας, προκειμένου να προωθεί τα μηνύματα εκπομπής κινητής τηλεφωνίας κατά τη λήψη τους. Οι ειδοποιήσεις εκπομπής κινητής τηλεφωνίας προβάλλονται σε ορισμένες τοποθεσίες, για να σας προειδοποιήσουν σχετικά με καταστάσεις έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές μπορεί να επηρεάσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μιας εκπομπής κινητής τηλεφωνίας έκτακτης ανάγκης."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Διαχείριση κλήσεων σε εξέλιξη"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Επιτρέπει σε μια εφαρμογή να βλέπει λεπτομέρειες σχετικά με τις κλήσεις σε εξέλιξη στη συσκευή σας και να τις ελέγχει."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 74b835e..de5dba2 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 8f8972c..7bd62aa 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2421e2a..b21b67d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index dd7b151..69acec6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0e14345..ae57206 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎Allows the app to receive and process MMS messages. This means the app could monitor or delete messages sent to your device without showing them to you.‎‏‎‎‏‎"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎Forward cell broadcast messages‎‏‎‎‏‎"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‎‎Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received.‎‏‎‎‏‎"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‎Manage ongoing calls‎‏‎‎‏‎"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎Allows an app to see details about ongoing calls on your device and to control these calls.‎‏‎‎‏‎"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎read cell broadcast messages‎‏‎‎‏‎"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎Allows the app to read cell broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received.‎‏‎‎‏‎"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎read subscribed feeds‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 780e481..f5bd810 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de emisión móvil"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la app se vincule al módulo de emisión móvil para reenviar los mensajes de este tipo a medida que se reciben. En algunas ubicaciones, se envían alertas de emisión móvil para advertirte en situaciones de emergencia. Es posible que las apps maliciosas interfieran con el rendimiento o el funcionamiento de tu dispositivo cuando recibes una emisión móvil de emergencia."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrar llamadas en curso"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una app vea detalles sobre las llamadas en curso del dispositivo y las controle."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite a la aplicación leer los mensajes de difusión móvil que recibe tu dispositivo. En algunas ubicaciones, las alertas de difusión móvil se envían para informar situaciones de emergencia. Las aplicaciones maliciosas pueden afectar el rendimiento o funcionamiento de tu dispositivo cuando se recibe un un mensaje de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer canales suscritos"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3c6b9e2..e234efbf 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de difusión móvil"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la aplicación se vincule con el módulo de difusión móvil para reenviar los mensajes de ese tipo en cuanto se reciben. En ciertas ubicaciones se envían alertas de difusión móvil para avisar de situaciones de emergencia. Cuando se recibe una alerta de difusión móvil de emergencia, ciertas aplicaciones malintencionadas podrían interferir en el rendimiento o en el funcionamiento del dispositivo."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestionar llamadas en curso"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una aplicación consulte datos de llamadas que estén en curso en tu dispositivo y controle esas llamadas."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"leer mensajes de difusión móvil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que la aplicación lea mensajes de difusión móvil que haya recibido el dispositivo. Las alertas de difusión móvil se envían en algunas ubicaciones para avisar de situaciones de emergencia. Es posible que las aplicaciones malintencionadas interfieran en el rendimiento o en el funcionamiento del dispositivo si se recibe una alerta de difusión móvil de emergencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer feeds a los que está suscrito el usuario"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 152a35e..543b5a1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Võimaldab rakendusel vastu võtta ja töödelda multimeediumsõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kärjeteadete edasisaatmine"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Võimaldab rakendusel luua ühenduse kärjeteadete mooduliga, et saabunud kärjeteateid edasi saata. Kärjeteateid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad seadme toimivust või tööd eriolukorra kärjeteate vastuvõtmisel segada."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Käimasolevate kõnede haldamine"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Võimaldab rakendusel näha teie seadmes käimasolevate kõnede üksikasju ja neid kõnesid hallata."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobiilsidesõnumite lugemine"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Võimaldab rakendusel lugeda seadme vastu võetud mobiilsidesõnumeid. Mobiilsidemärguandeid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad segada seadme toimivust või tööd eriolukorra sõnumi vastuvõtmisel."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"loe tellitud kanaleid"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4fa4d06..c552e8f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio gaiztoek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Kudeatu abian dauden deiak"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gailuak jasotzen dituen deiei buruzko xehetasunak ikusteko eta dei horiek kontrolatzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"irakurri harpidetutako jarioak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9efe16b..3d523fd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"به برنامه اجازه می‌دهد پیام‌های فراپیام را دریافت و پردازش کند. این یعنی برنامه می‌تواند پیام‌های ارسالی به دستگاه شما را بدون نمایش آن‌ها به شما حذف یا کنترل کند."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"بازارسال پیام‌های پخش سلولی"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"به برنامه امکان می‌دهد به مدول پخش سلولی متصل شود تا پیام‌های پخش سلولی را به محض دریافت بازارسال کند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی ارسال می‌شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‌شود، ممکن است برنامه‌های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"مدیریت تماس‌های درحال انجام"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"به برنامه اجازه می‌دهد جزئیات تماس‌های درحال انجام در دستگاه را ببیند و این تماس‌ها را کنترل کند."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"خواندن پیام‌های پخش سلولی"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"‏به برنامه اجازه می‎دهد پیام‌های پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیت‌های مکانی تحویل داده می‎شوند تا موقعیت‌های اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت می‎شود، ممکن است برنامه‎های مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"خواندن فیدهای مشترک"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 80c8ebe..81546d9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Lähetä solulähetysviestit edelleen"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sallii sovelluksen sitoutua solulähetysmoduuliin lähettääkseen solulähetysviestejä edelleen sitä mukaa kun ne saapuvat. Solulähetysilmoitusten avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätilanteeseen liittyvän solulähetysviestin."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ylläpidä käynnissä olevia puheluita"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Sovellus voi nähdä tietoja laitteella käynnissä olevista puheluista ja ohjata näitä puheluita."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lue tiedotteita"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Antaa sovelluksen lukea laitteesi vastaanottamia tiedotteita. Tiedotteiden avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätiedotteen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lukea tilattuja syötteitä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 8bc6d37..cdfa15d 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -356,6 +356,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les messages multimédias. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages de diffusion cellulaire"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet à l\'application d\'établir un lien avec le module de diffusion cellulaire afin de transférer les messages de diffusion cellulaire à mesure de leur réception. Dans certaines régions, des alertes de diffusion cellulaire sont envoyées afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages de diffusion cellulaire que votre appareil reçoit. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Des applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lors de la réception d\'un message de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7d5e10b..9e0f60c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -356,6 +356,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les MMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages reçus via un canal de diffusion cellulaire"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Autorise l\'application à établir une connexion avec le module de diffusion cellulaire afin de transférer les messages reçus via un canal de diffusion cellulaire. Des alertes de diffusion cellulaire sont générées dans certaines régions afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages reçus via un canal de diffusion cellulaire"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages que votre appareil reçoit via un canal de diffusion cellulaire. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Les applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lorsqu\'un message est reçu via un canal de diffusion cellulaire."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index c1d8703..423b97f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensaxes de difusión móbil"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a aplicación se vincule ao módulo de difusión móbil para reenviar as mensaxes deste tipo segundo se reciban. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. As aplicacións maliciosas poden interferir no rendemento ou funcionamento do teu dispositivo cando se reciba unha difusión móbil de emerxencia."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensaxes de difusión móbil"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 794b7a7..14347ee 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"ઍપ્લિકેશનને MMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"સેલ બ્રોડકાસ્ટ સંદેશા ફૉરવર્ડ કરો"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"સેલ બ્રોડકાસ્ટ સંદેશા પ્રાપ્ત થાય કે તરત ફૉરવર્ડ કરવા માટે સેલ બ્રોડકાસ્ટ મૉડ્યૂલ સાથે પ્રતિબદ્ધ થવા બાબતે ઍપને મંજૂરી આપે છે. તમને કટોકટીની પરિસ્થિતિની ચેતવણી આપવા માટે સેલ બ્રોડકાસ્ટ અલર્ટ અમુક સ્થાનોમાં ડિલિવર કરવામાં આવે છે. કટોકટી અંગેનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય, ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઑપરેશનમાં વિક્ષેપ પાડે તેમ બની શકે છે."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index dc44fba..e63e502 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्‍हें हटा सकता है."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल ब्रॉडकास्ट (CBC) मैसेज दूसरे नंबर पर भेजें"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल ब्रॉडकास्ट (CBC) मैसेज आते ही उसे दूसरे नंबर पर भेजने के लिए, ऐप्लिकेशन को सेल ब्रॉडकास्ट (CBC) मॉड्यूल पर बाइंड करने की अनुमति देता है. कुछ जगहों में सेल ब्रॉडकास्ट (CBC) अलर्ट आपातकालीन स्थितियों के बारे में चेतावनी देने के लिए भेजा जाता है. नुकसान पहुंचाने वाले ऐप्लिकेशन, आपातकाल में सेल ब्रॉडकास्ट (CBC) मैसेज मिलने पर आपके डिवाइस के काम करते समय या इसके परफ़ॉर्मेंस में रुकावट पैदा कर सकते हैं."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"चल रहे कॉल प्रबंधित करें"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"इससे, ऐप्लिकेशन को आपके डिवाइस पर चल रहे कॉल की जानकारी देखने और उन्हें कंट्रोल करने की अनुमति मिलती है."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्‍थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता वाली फ़ीड पढ़ें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index deaac3f..45c89a6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -356,6 +356,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka emitiranja na mobitele"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Omogućuje aplikaciji da se poveže s modulom za emitiranje na mobitele kako bi prosljeđivala poruke koje se emitiraju na mobitele po njihovom primitku. Upozorenja značajke emitiranja na mobitele dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno emitiranje na mobitele."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje tekućim pozivima"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućuje aplikaciji pregled pojedinosti o tekućim pozivima na uređaju i upravljanje tim pozivima."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućuje aplikaciji čitanje poruka emitiranih unutar mobilne mreže koje prima vaš uređaj. Upozorenja koja se emitiraju na području mobilne mreže dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno upozorenje koje se emitira unutar mobilne mreže."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje pretplaćenih feedova"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c408395..ec0715b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Lehetővé teszi az alkalmazás számára, hogy MMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cellán belüli üzenetek továbbítása"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Az alkalmazás összekapcsolódhat a cellán belüli üzenetszórás moduljával, hogy az érkezésükkor továbbítani tudja a cellán belüli üzeneteket. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások vészhelyzeti cellaüzenet érkezésekor befolyásolhatják az eszköz teljesítményét és működését."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"cellán belüli üzenetek olvasása"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lehetővé teszi az alkalmazás számára az eszközre érkező cellán belüli üzenetek olvasását. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások befolyásolhatják az eszköz  teljesítményét vagy működését vészhelyzeti cellaüzenet érkezésekor."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"feliratkozott hírcsatornák olvasása"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b1db764..b28e5fd 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Թույլ է տալիս հավելվածին ստանալ և մշակել MMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Բջջային հեռարձակման հաղորդագրությունների վերահասցեավորում"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Թույլ է տալիս հավելվածին կապ հաստատել բջջային հեռարձակման մոդուլի հետ՝ բնակչությանը ծանուցող հաղորդագրությունները վերահասցեավորելու համար։ Որոշ երկրներում այս հաղորդագրություններն օգտագործվում են բնակչությանը արտակարգ իրավիճակների մասին զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի աշխատանքին, որին ուղարկվում են այս հաղորդագրությունները:"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ընթացիկ զանգերի կառավարում"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Թույլ է տալիս հավելվածին ձեր սարքում տեսնել ընթացիկ զանգերի մասին տեղեկությունները և կառավարել այդ զանգերը։"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"կարդալ բաժանորդագրված հոսքերը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index fc82c22..099f819 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Memungkinkan aplikasi menerima dan memproses pesan MMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Teruskan pesan cell broadcast"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Mengizinkan aplikasi mem-binding ke modul cell broadcast untuk meneruskan pesan cell broadcast saat pesan tersebut diterima. Notifikasi cell broadcast dikirim di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu performa atau operasi perangkat saat cell broadcast darurat diterima."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"membaca pesan siaran seluler"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Mengizinkan aplikasi membaca pesan siaran seluler yang diterima perangkat Anda. Notifikasi siaran seluler dikirimkan di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu kinerja atau operasi perangkat Anda saat siaran seluler darurat diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca feed langganan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 456f518..867fca8 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Leyfir forriti að taka á móti og vinna úr MMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Framsenda skilaboð frá endurvarpa"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Heimilar forritinu að bindast endurvarpseiningunni til að framsenda skilaboð frá endurvarpa þegar þau berast. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Stjórna símtölum sem eru í gangi"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Leyfir forriti að sjá upplýsingar um og stjórna símtölum sem eru í gangi í tækinu þínu."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lesa skilaboð frá endurvarpa"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Leyfir forriti að lesa skilaboð frá endurvarpa sem tækið móttekur. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lesa strauma í áskrift"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e89145b..6f2e158 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Consente all\'applicazione di ricevere ed elaborare messaggi MMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Inoltro di messaggi cell broadcast"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Consente all\'app di essere associata al modulo di cell broadcast al fine di inoltrare i messaggi di cell broadcast man mano che arrivano. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestione delle chiamate in corso"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Consente a un\'app di accedere a dettagli relativi alle chiamate in corso sul tuo dispositivo e di controllare tali chiamate."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lettura di messaggi cell broadcast"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lettura feed sottoscritti"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a8810ab..2846508 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"‏מאפשר לאפליקציה לקבל ולעבד הודעות MMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"העברת הודעות של שידור סלולרי"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"מאפשרת לאפליקציה להתחייב למודול של השידור הסלולרי כדי להעביר הודעות של שידור סלולרי כשהן מתקבלות. התראות שידור סלולרי נשלחות במקומות מסוימים כדי להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר כאשר מתקבל שידור חירום סלולרי."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ניהול שיחות שנערכות"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"לאפליקציה תהיה אפשרות לראות פרטים על שיחות שנערכות במכשיר ולשלוט בשיחות האלה."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"קריאת הודעות שידור סלולרי"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"קרא עדכוני מנויים"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 079598b..c6e8a14 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"緊急速報メールの転送"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"受信した緊急速報メールを転送するために、緊急速報メール モジュールにバインドすることをこのアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"通話の管理"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"デバイスでの通話に関する詳細の参照と、通話の操作をアプリに許可します。"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"緊急速報メール SMS の読み取り"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"登録したフィードの読み取り"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 22d69d6..912930f 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"აპს შეეძლება MMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast შეტყობინებების გადამისამართება"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"საშუალებას აძლევს აპს, დაუკავშირდეს cell broadcast მოდულს იმისთვის, რომ გადაამისამართოს cell broadcast შეტყობინებები მათი მიღებისთანავე. Cell broadcast გაფრთხილებები მიეწოდება ზოგიერთ მდებარეობაზე საგანგებო სიტუაციების შესახებ გაფრთხილების მიზნით. საგანგებო cell broadcast-ის მიღების დროს, მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"მიმდინარე ზარების მართვა"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"საშუალებას აძლევს აპს, ნახოს თქვენს მოწყობილობაზე მიმდინარე ზარების დეტალები და აკონტროლოს ეს ზარები."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"გამოწერილი არხების წაკითხვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 464b798..d615538 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Қолданбаға MMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Ұялы таратылым хабарларының бағытын өзгерту"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ұялы таратылым хабарлары алынғаннан кейін, олардың бағытын өзгерту үшін қолданбаға ұялы таратылым модулімен байланыстыруға мүмкіндік береді. Ұялы таратылым ескертулері кей аймақтарда төтенше жағдайлар туралы хабарлау үшін беріледі. Төтенше жағдай туралы ұялы таратылым хабары алынғаннан кейін, зиянды қолданбалар құрылғы жұмысына кедергі келтіруі мүмкін."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Қазіргі қоңырауларды басқару"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Қолданбаға құрылғыдағы қазіргі қоңыраулар туралы мәліметтерді көруге және басқаруға мүмкіндік береді."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ұялы хабар тарату хабарларын оқу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылған ағындарды оқу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 823a574..075a652 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"ឲ្យ​កម្មវិធី​ទទួល និង​ដំណើរការ​​សារ​ MMS ។ វា​មាន​ន័យ​ថា កម្មវិធី​អាច​តាមដាន​ ឬ​លុប​សារ​ដែល​បាន​ផ្ញើ​ទៅ​ឧបករណ៍​របស់​អ្នក​ដោយ​មិន​បង្ហាញ​ពួកវា។"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"បញ្ជូន​សារ​ផ្សាយចល័ត​បន្ត"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"អនុញ្ញាតឱ្យ​កម្មវិធី​ភ្ជាប់ទៅ​ម៉ូឌុល​ការផ្សាយចល័ត ដើម្បីបញ្ជូន​សារផ្សាយ​ចល័តបន្ត នៅពេល​ទទួលបាន​សារទាំងនោះ។ ការជូនដំណឹងអំពី​ការផ្សាយចល័ត​ត្រូវបានបញ្ជូនទៅ​ទីតាំងមួយចំនួន ដើម្បីព្រមាន​អ្នក​អំពីស្ថានភាព​អាសន្ន។ កម្មវិធី​គ្រោះថ្នាក់​អាច​រំខាន​ដល់ដំណើរការ ឬប្រតិបត្តិការ​ឧបករណ៍​របស់អ្នក នៅពេល​ទទួលបានការផ្សាយ​ចល័តពេលមានអាសន្ន​។"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"គ្រប់គ្រង​ការហៅទូរសព្ទដែល​កំពុងដំណើរការ"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"អនុញ្ញាតឱ្យ​កម្មវិធីមើលព័ត៌មានលម្អិត​អំពីការហៅទូរសព្ទ​ដែលកំពុងដំណើរការ​នៅលើឧបករណ៍​របស់អ្នក និងគ្រប់គ្រង​ការហៅទូរសព្ទទាំងនេះ។"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"អាន​សារ​ប្រកាស​ចល័ត"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ឲ្យ​កម្មវិធី​អាន​សារ​ប្រកាស​ការ​ហៅ​ដែល​ឧបករណ៍​របស់​​អ្នក​បាន​ទទួល។ ការ​ជូន​ដំណឹង​ប្រកាស​ចល័ត​ត្រូវ​បាន​បញ្ជូន​ទៅ​ទីតាំង​មួយ​ចំនួន ដើម្បី​ព្រមាន​អ្នក​អំពី​ស្ថានភាព​អាសន្ន។ កម្មវិធី​ព្យាបាទ​អាច​ជ្រៀតជ្រែក​ការ​អនុវត្ត ឬ​ប្រតិបត្តិការ​ឧបករណ៍​របស់​អ្នក​​ពេល​ទទួល​ការ​ប្រកាស​ចល័ត​ពេល​អាសន្ន។"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"អាន​អត្ថបទ​ព័ត៌មាន​បាន​ជាវ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index bac30ef..61ed9b3 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡಿ"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ಸೆಲ್ ಪ್ರಸಾರವು ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ರೀತಿಯಲ್ಲಿಯೇ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು, ಸೆಲ್ ಪ್ರಸಾರ ಮಾಡ್ಯುಲ್‌ ಅನ್ನು ಪ್ರತಿಬಂಧಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ತುರ್ತು ಸ್ಥಿತಿಗಳ ಕುರಿತು ನಿಮಗೆ ಎಚ್ಚರಿಸಲು ಸೆಲ್ ಪ್ರಸಾರದ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತುರ್ತು ಸೆಲ್‌ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸಿದಾಗ ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಾಚರಣೆ ಅಥವಾ ಕಾರ್ಯಕ್ಷಮತೆಗೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್‌ಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್‌‌‌ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ಚಂದಾದಾರ ಫೀಡ್‌ಗಳನ್ನು ಓದಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 00eb66f..dfa3770 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"앱이 MMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"셀 브로드캐스트 메시지 전달"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"셀 브로드캐스트 메시지를 수신하자마자 전달하기 위해 앱이 셀 브로드캐스트 모듈에 연결하도록 허용합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"셀 브로드캐스트 메시지 읽기"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"가입된 피드 읽기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 7c1fb98..bd6ecef 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Колдонмого MMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Уюк жөнөтүүлөрүнүн билдирүүлөрүн башка номерге багыттоо"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Уюк жөнөтүүлөрүнүн билдирүүлөрү келген сайын башка номерге багыттап туруу үчүн колдонмого уюк жөнөтүүлөрүнүн модулу менен байланышууга уруксат берет. Шашылыш уюк жөнөтүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралуу сизге эскертүү үчүн жөнөтүлөт. Зыянкеч колдонмолор шашылыш уюк жөнөтүүлөрү кабыл алынганда түзмөктүн майнаптуулугуна же иштешине жолтоо болушу мүмкүн."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"уюктук берүү билдирүүлөрүн окуу"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылган түрмөктөрдү окуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 72bd141..c60d594 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"ອະນຸຍາດໃຫ້ແອັບຯ ຮັບແລະປະມວນຜົນຂໍ້ຄວາມ MMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບ"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ອະນຸຍາດໃຫ້ແອັບຜູກມັດກັບໂມດູນການກະຈາຍສັນຍານໂທລະສັບເພື່ອສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບເມື່ອໄດ້ຮັບມາ. ການເຕືອນການກະຈາຍສັນຍານໂທລະສັບແມ່ນຖືກຈັດສົ່ງໃນບາງສະຖານທີ່ເພື່ອເຕືອນທ່ານໃນກໍລະນີມີເຫດການສຸກເສີນເກີດຂຶ້ນ. ແອັບທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼື ການເຮັດວຽກຂອງອຸປະກອນທ່ານເມື່ອໄດ້ຮັບການກະຈາຍສັນຍານໂທລະສັບສຸກເສີນ."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ຈັດການສາຍໂທອອກ"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ອະນຸຍາດໃຫ້ແອັບໃດໜຶ່ງເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບສາຍໂທອອກຢູ່ອຸປະກອນຂອງທ່ານ ແລະ ເພື່ອຄວບຄຸມການໂທເຫຼົ່ານີ້."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a4e1756..39cbbe1 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Leidžiama programai gauti ir apdoroti MMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Persiųsti mobiliuoju transliuojamus pranešimus"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Programai leidžiama susaistyti transliacijos mobiliuoju modulį, kad būtų galima persiųsti mobiliuoju transliuojamus pranešimus, kai jie gaunami. Transliacijos mobiliuoju įspėjimai pristatomi kai kuriose vietovėse, kad būtų galima įspėti apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Tvarkyti vykstančius skambučius"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Programai leidžiama peržiūrėti išsamią informaciją apie vykstančius skambučius įrenginyje ir valdyti šiuos skambučius."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"skaityti mobiliuoju transliuojamus pranešimus"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Programai leidžiama skaityti mobiliuoju transliuojamus pranešimus, gaunamus jūsų įrenginyje. Mobiliuoju transliuojami įspėjimai pristatomi kai kuriose vietose, kad įspėtų apie kritines situacijas. Kai gaunamas  mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"skaityti prenumeruojamus tiekimus"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 088e78d..49d3f44 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -356,6 +356,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Ļauj lietotnei saņemt un apstrādāt multiziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Pārsūtīt šūnu apraides ziņojumus"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ļauj piesaistīt lietotni šūnu apraides modulim, lai pārsūtītu šūnu apraides ziņojumus, tiklīdz tie tiek saņemti. Šūnu apraides brīdinājumi tiek piegādāti noteiktās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"šūnu apraides ziņojumu lasīšana"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ļauj lietotnei lasīt ierīcē saņemtos šūnu apraides ziņojumus. Šūnu apraides brīdinājumi tiek piegādāti dažās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lasīt abonētās plūsmas"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 23a84c6..63375f5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Овозможува апликацијата да прима и да обработува MMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Проследување пораки за мобилен пренос"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволува апликацијата да се врзе со модулот за мобилен пренос за да проследува пораки за мобилен пренос штом ќе се примат. Предупредувањата за мобилно емитување се доставуваат на некои локации за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управување со тековни повици"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Дозволува апликацијата да гледа детали за тековните повици на уредот и да ги контролира овие повици."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"прочитај пораки за мобилно емитување"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читај претплатени навестувања на содржина"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1c89b33..3eca56c 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്‌ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുക"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"സ്വീകരിക്കുന്ന മുറയ്ക്ക് ബ്രോഡ്‌കാസ്‌റ്റ് സന്ദേശങ്ങൾ കൈമാറുന്നതിന് സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് മോഡ്യൂളിലേക്ക് ബൈൻഡ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെ കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകുന്നതിന് ചില ലൊക്കേഷനുകളിൽ സെൽ ബ്രോഡ്‌കാസ്‌റ്റ് അലേർട്ടുകൾ ഡെലിവറി ചെയ്യപ്പെടുന്നു. ഒരു അടിയന്തര സെൽ ബ്രോഡ്‌കാസ്റ്റ് ലഭിക്കുമ്പോൾ ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെയോ പ്രവർത്തനത്തെയോ തടസപ്പെടുത്താനിടയുണ്ട്."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"സബ്‌സ്ക്രൈബ് ചെയ്‌ത ഫീഡുകൾ വായിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 919112a..366a5b7 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Апп нь MMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг шилжүүлэх"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг хүлээн авах үед түүнийг шилжүүлэх зорилгоор аппад гар утсанд масс мессеж түгээх модультай холбогдохыг зөвшөөрөх Гар утсанд масс мессеж түгээх онцлогийн сэрэмжлүүлэг нь онцгой нөхцөл байдлын тухай танд анхааруулахын тулд зарим байршилд хүрдэг. Гар утсанд масс мессеж түгээх онцлогийн илгээх онцгой нөхцөл байдлын тухай мессежийг хүлээн авах үед хортой апп таны төхөөрөмжийн гүйцэтгэл эсвэл ажиллагаанд саад учруулж болзошгүй."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Үргэлжилж буй дуудлагыг удирдах"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Аппад таны төхөөрөмж дээрх үргэлжилж буй дуудлагын талаарх дэлгэрэнгүйг харах болон эдгээр дуудлагыг хянахыг зөвшөөрнө."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"үүрэн өргөн дамжууллын мессеж унших"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"бүртгүүлсэн хангамжийг унших"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 7a8fd1a..197797f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अ‍ॅप ला अनुमती देते. म्हणजेच अ‍ॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल प्रसारण मेसेज फॉरवर्ड करा"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल प्रसारण मेसेज मिळाल्यानंतर ते फॉरवर्ड करण्यासाठी ॲपला सेल प्रसारण मॉड्यूलमध्ये प्रतिबद्ध करण्याची अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थीतींची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरित केल्या जातात. दुर्भावनापूर्ण अ‍ॅप्स आणीबाणी सेल प्रसारण मिळवतात तेव्हा ती तुमच्या डिव्हाइसच्या परफॉर्मन्समध्ये किंवा कामामध्ये कदाचित व्यत्यय आणू शकतात."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारण मेसेज वाचा"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अ‍ॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अ‍ॅप्स व्यत्यय आणू शकतात."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता घेतलेली फीड वाचा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index e94dcde..635c5b7 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Membenarkan apl menerima dan memproses mesej MMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kirim semula mesej siaran sel"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Membenarkan apl terikat pada modul siaran sel untuk mengirim semula mesej siaran sel apabila diterima. Makluman siaran sel dihantar di sesetengah lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"baca mesej siaran sel"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Membolehkan apl membaca mesej siaran sel yang diterima oleh peranti anda. Isyarat siaran sel dihantar di beberapa lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca suapan langganan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index c31b7b2..96d4417 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"အပလီကေးရှင်းအား ရုပ်သံစာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို ထပ်ဆင့်ပို့ခြင်း"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"စာတို ဖြန့်ဝေခြင်းစနစ် မော်ဂျူးကိုပေါင်းရန် အက်ပ်များအား ခွင့်ပြုသည်။ ၎င်းမှာ စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို လက်ခံရရှိသည့်အတိုင်း ထပ်ဆင့်ပို့ရန် ဖြစ်သည်။ အချို့တည်နေရာများတွင် သင့်အား အရေးပေါ်အခြေအနေများကို သတိပေးရန် စာတို ဖြန့်ဝေခြင်းစနစ်သုံး သတိပေးချက်များကို ပေးပို့သည်။ အရေးပေါ် စာတို ဖြန့်ဝေခြင်းကို ရရှိသည့်အခါ သံသယဖြစ်နိုင်ဖွယ်ရှိသည့် အက်ပ်များက သင့်စက်၏ စွမ်းဆောင်ရည်နှင့် အော်ပရေးရှင်းတို့ကို အနှောင့်အယှက်ပေးနိုင်သည်။"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"လက်ရှိခေါ်ဆိုမှုများကို စီမံခြင်း"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"သင့်စက်ပစ္စည်းပေါ်ရှိ လက်ရှိခေါ်ဆိုမှုများအကြောင်း အသေးစိတ်များကို ကြည့်ရှုရန်နှင့် ဤခေါ်ဆိုမှုများကို ထိန်းချုပ်ရန် အက်ပ်အား ခွင့်ပြုသည်။"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။  အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7f2c6aa..c85626f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend kringkastede meldinger"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillat at denne appen binder seg til modulen for kringkastede meldinger for å videresende kringkastede meldinger når de mottas. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrer pågående anrop"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gir en app tillatelse til å se informasjon om pågående anrop på enheten og til å kontrollere disse anropene."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lese kringkastede meldinger"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lese abonnement på nyhetskilder"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d555b7c..d1ae9ab 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"एपलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले एपलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्‌कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक एपहरूले आपत्‌कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू एपलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपत्‌कालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब एपहरूले एउटा आपत्‌कालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 04f598d..9d470b8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Hiermee kan de app MMS-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast-berichten doorsturen"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Hiermee kan de app de module voor cell broadcasts binden om cell broadcast-berichten door te sturen als die worden ontvangen. Cell broadcast-waarschuwingen worden op bepaalde locaties verzonden om je te waarschuwen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren als een bericht met een noodmelding wordt ontvangen."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Actieve gesprekken beheren"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Hiermee kan een app informatie over actieve gesprekken op je apparaat bekijken en deze gesprekken beheren."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"infodienstberichten lezen"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Toestaan dat de app infodienstberichten leest die worden ontvangen op je apparaat. Infodienstberichten worden verzonden naar bepaalde locaties om u te waarschjeen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren wanneer een infodienstbericht wordt ontvangen."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Geabonneerde feeds lezen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index bccb824..df72172 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ମେସେଜ୍‌ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍‍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍‍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍‍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍‍ଟି ମନିଟର୍‍ କିମ୍ବା ଡିଲିଟ୍‍ କରିପାରେ।"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ଫର୍‍ୱାର୍ଡ କରନ୍ତୁ"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ପ୍ରାପ୍ତ ହେବା ପରେ ସେଗୁଡ଼ିକୁ ଫର୍‍ୱାର୍ଡ କରିବା ପାଇଁ ଆପ୍‍କୁ ସେଲ୍ ପ୍ରସାରଣ ମଡ୍ୟୁଲ୍ ସହିତ ସଂଯୁକ୍ତ କରିବାକୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ପରିସ୍ଥିତିରେ ଆପଣଙ୍କୁ ଚେତାବନୀ ଦେବା ପାଇଁ କିଛି ଲୋକେସନ୍‍‍ରେ ସେଲ୍ ପ୍ରସାରଣ ଆଲର୍ଟ ବିତରଣ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ପ୍ରସାରଣ ପ୍ରାପ୍ତ ହେବା ସମୟରେ କିଛି କ୍ଷତିକାରକ ଆପ୍ସ ହୁଏତ ଆପଣଙ୍କର ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟଦକ୍ଷତା କିମ୍ବା କାର୍ଯ୍ୟ ପ୍ରକ୍ରିୟାରେ ହସ୍ତକ୍ଷେପ କରିପାରେ।"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢ଼ନ୍ତୁ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ଆପଣଙ୍କ ଡିଭାଇସ୍‍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ମେସେଜ୍‍ ପଢିବାକୁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍‍ରେ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍‍ ବ୍ରଡ୍‍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍‍ ଆପଣଙ୍କ ଡିଭାଇସ୍‍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍‌କୁ ପଢ଼ନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2d16de8..9736e57 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ਐਪ ਨੂੰ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਦੇ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹੀ ਉਹਨਾਂ ਨੂੰ ਅੱਗੇ ਭੇਜਣ ਲਈ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਮਾਡਿਊਲ ਨਾਲ ਜੋੜਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਚੇਤਨਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਟਿਕਾਣਿਆਂ \'ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9534359..295a54e 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -359,6 +359,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Pozwala aplikacji na odbieranie i przetwarzanie MMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Przekaż komunikaty z sieci komórkowej"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Zezwala aplikacji powiązać się z modułem komunikatów z sieci komórkowej, aby przekazywać je w momencie, w którym są otrzymywane. W niektórych lokalizacjach komunikaty alarmowe z sieci komórkowej są dostarczane, aby ostrzec Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na działanie urządzenia lub zakłócać je po nadejściu komunikatu alarmowego z sieci komórkowej."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"odczyt komunikatów z sieci komórkowej"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Zezwala aplikacji na odczyt komunikatów z sieci komórkowej odebranych na urządzeniu. Komunikaty alarmowe z sieci komórkowej są dostarczane w niektórych lokalizacjach w celu ostrzeżenia Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na wydajność lub zakłócać działanie urządzenia po odebraniu komunikatu alarmowego z sieci komórkowej."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"czytanie subskrybowanych źródeł"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 8198a62..d9050bf 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 71dd2b9..3de02ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que a app receba e processe mensagens MMS. Isto significa que a app poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de difusão celular"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a app se vincule ao módulo de difusão celular para encaminhar mensagens de difusão celular à medida que são recebidas. Os alertas de difusão celular são fornecidos em algumas localizações para avisar sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma difusão celular de emergência."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerir chamadas em curso"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que uma app veja detalhes acerca das chamadas em curso no seu dispositivo e controle essas chamadas."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de transmissão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que a app leia mensagens de transmissão celular recebidas pelo seu dispositivo. Os alertas de transmissão celular são fornecidos em algumas localizações para avisá-lo sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma transmissão celular de emergência."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8198a62..d9050bf 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4d091e9..340b752 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -356,6 +356,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Redirecționează mesajele cu transmisie celulară"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite aplicației să se conecteze la modulul de transmisie celulară pentru a redirecționa mesajele cu transmisie celulară pe măsură ce le primește. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"citește mesajele cu transmisie celulară"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"citire feeduri abonat"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 783ec9a..74d5bf9 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -359,6 +359,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Приложение сможет получать и обрабатывать MMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пересылка сообщений для оповещения населения"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Читать сообщения массовой рассылки"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Просмотр фидов пользователя"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 74b4008..6c1c777 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS පණිවිඩ සොයා ලබාගැනීමට සහ ක්‍රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. යෙදුම නිරීක්ෂණය කරනු ලබන අතර ඔබට ලැබුන පණිවිඩ පෙන්වීමෙන් තොරවම මකා දැමිය හැකි බව මෙමඟින් අදහස් කරයි."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"සෙල් විකාශන පණිවිඩ යොමු කිරීම"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"සෙල් විකාශන පණිවිඩ ලැබුණු විට ඒවා යොමු කිරීම සඳහා සෙල් විකාශන මොඩියුලයට බැඳීමට යෙදුමට ඉඩ දෙයි. හදිසි අවස්ථා පිළිබඳව ඔබට අනතුරු ඇඟවීම සඳහා සෙල් විකාශන ඇඟවීම් සමහර ස්ථානවල ලබා දෙනු ලැබේ. හදිසි සෙල් විකාශනයක් ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම්වලින් ඔබගේ උපාංග කාර්ය සාධනයට හෝ මෙහෙයුමට බාධා සිදු විය හැකිය."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"සිදු වෙමින් පවතින ඇමතුම් කළමනාකරණය කරන්න"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ඔබගේ උපාංගයේ සිදු වෙමින් පවතින ඇමතුම් පිළිබඳ විස්තර බැලීමට සහ මෙම ඇමතුම් පාලනය කිරීමට යෙදුමකට ඉඩ දෙයි."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"සෙල් ප්‍රචාරණ පණිවිඩ කියවීම"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්‍රියකරණයට බාධා සිදුවිය හැක."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"දායක වූ සංග්‍රහ කියවීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 74e2b69..cfffb86 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -162,7 +162,7 @@
     <string name="httpErrorAuth" msgid="469553140922938968">"Nepodarilo sa overiť totožnosť."</string>
     <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Overenie pomocou servera proxy bolo neúspešné."</string>
     <string name="httpErrorConnect" msgid="3295081579893205617">"K serveru sa nepodarilo pripojiť."</string>
-    <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to znova neskôr."</string>
+    <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to neskôr."</string>
     <string name="httpErrorTimeout" msgid="7446272815190334204">"Časový limit pripojenia na server vypršal."</string>
     <string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Stránka obsahuje príliš veľa presmerovaní servera."</string>
     <string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"Protokol nie je podporovaný."</string>
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Preposielanie správ informačných služieb"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikácii spojiť sa s modulom správ informačných služieb s cieľom preposielať prichádzajúce správy informačných služieb. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa prebiehajúcich hovorov"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Povolí aplikácii čítať podrobnosti o prebiehajúcich hovoroch v zariadení a ovládať ich."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čítať správy informačných služieb"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikácii čítať správy informačných služieb prijaté vaším zariadením. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čítať odoberané informačné kanály"</string>
@@ -572,7 +574,7 @@
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string>
-    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
     <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string>
@@ -616,7 +618,7 @@
     <string name="face_error_no_space" msgid="5649264057026021723">"Nové údaje o tvári sa nedajú uložiť. Najprv odstráňte jeden zo starých záznamov."</string>
     <string name="face_error_canceled" msgid="2164434737103802131">"Operácia týkajúca sa tváre bola zrušená"</string>
     <string name="face_error_user_canceled" msgid="8553045452825849843">"Odomknutie tvárou zrušil používateľ."</string>
-    <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+    <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to neskôr."</string>
     <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Príliš veľa pokusov. Odomknutie tvárou bolo zakázané."</string>
     <string name="face_error_unable_to_process" msgid="5723292697366130070">"Nedá sa overiť tvár. Skúste to znova."</string>
     <string name="face_error_not_enrolled" msgid="7369928733504691611">"Nenastavili ste odomknutie tvárou."</string>
@@ -1824,7 +1826,7 @@
       <item quantity="other">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekúnd</item>
       <item quantity="one">Skúste to znova o 1 sekundu</item>
     </plurals>
-    <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to znova neskôr"</string>
+    <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to neskôr"</string>
     <string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazenie na celú obrazovku"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 755db5c..2a027b2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -359,6 +359,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogoča prejemanje in obdelavo MMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Posredovanje sporočil oddaj v celici"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Aplikaciji omogoča povezovanje z modulom za oddaje v celici, da posreduje sporočila oddaj v celici, takoj ko jih prejme. Na nekaterih lokacijah so opozorila oddaj v celici dostavljena, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko prejme sporočilo oddaje v celici."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje aktivnih klicev"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Aplikaciji dovoljuje ogled podrobnosti o aktivnih klicih v napravi in upravljanje s temi klici."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"branje sporočil oddaje v celici"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogoča aplikaciji branje sporočil oddaje v celici, ki jih prejme naprava. Opozorila oddaje v celici so dostavljena na nekaterih lokacijah, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko dobi sporočilo oddaje v celici."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"branje naročenih virov"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index bd970a0..25989bd9 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Lejon aplikacionin të marrë dhe përpunojë mesazhe MMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transmeto mesazhet e transmetimit celular"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Lejon që aplikacioni të lidhet me modulin e transmetimit celular për t\'i transferuar mesazhet e transmetimit celular menjëherë kur merren. Sinjalizimet e transmetimit celular dërgohen në disa vendndodhje për të të paralajmëruar për situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në cilësinë e funksionimit ose në veprimin e pajisjes sate kur merret një transmetim celular urgjent."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lexo mesazhet e transmetimit të qelizës"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lejon aplikacionin të lexojë mesazhet e transmetimit të qelizës, të marra nga pajisja jote. Alarmet e transmetimit të qelizës dërgohen në disa vendndodhje për të të paralajmëruar në situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në veprimtarinë ose operacionin e pajisjes tënde kur merret një transmetim urgjent i qelizës."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lexo informacione të abonuara"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a3acb3d..fe12013 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -356,6 +356,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Прослеђивање порука за мобилне уређаје на локалитету"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управљање одлазним позивима"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Омогућава апликацији да види детаље о одлазним позивима на уређају и да контролише те позиве."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читање порука инфо сервиса"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читање пријављених фидова"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ddd3faa..60b14ff 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Tillåter att appen tar emot och hanterar MMS-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Vidarebefordra massutskick via sms"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillåter att appen binds till cellsändningsmodulen så att massutskick via sms kan vidarebefordras vid mottagandet. I vissa områden används massutskick via sms för att varna om nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktioner när ett massutskick via sms tas emot."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Hantera pågående samtal"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Tillåter att en app får åtkomst till information om pågående samtal på enheten och kan kontrollera dessa samtal."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"läsa SMS-meddelanden"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"läsa flöden som du prenumererar på"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 62b1c06..0818d80 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Inaruhusu programu kupokea na kuchakata ujumbe medianwai (MMS). Hii inamaanisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwa kifaa chako bila ya kukuonyesha."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Sambaza ujumbe wa matangazo ya simu"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Huruhusu programu ipachikwe katika sehemu ya matangazo ya simu ili isambaze ujumbe wa matangazo ya simu unapopokewa. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendaji au shughuli ya kifaa chako matangazo ya simu ya dharura yanapopokewa."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"soma mawasiliano ya matangazo ya simu"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Huruhusu programu kusoma mawasiliano ya matangazo ya simu yaliyoingia kwenye kifaa chako. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendajikazi au shughuli ya kifaa chako wakati matangazo ya simu ya dharura yameingia."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 28a9cb7..0fe5962 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்கவோ, நீக்கவோ ஆப்ஸால் முடியும் என்பதாகும்."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"செல் பிராட்காஸ்ட் மெசேஜ்களை முன்னனுப்பு"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"செல் பிராட்காஸ்ட் மெசேஜ்களைப் பெறும்போதெல்லாம் அவற்றை முன்னனுப்பும் பொருட்டு, ஆப்ஸை செல் பிராட்காஸ்ட் மாடியூலோடு இணைக்கும். சில இடங்களில் அவசர சூழ்நிலைகளின் போது உங்களை எச்சரிக்க செல் பிராட்காஸ்ட் விழிப்பூட்டல்கள் அனுப்பப்படும். அவசரநிலை செல் பிராட்காஸ்ட்டைப் பெறும்போது, தீங்கிழைக்கும் ஆப்ஸ் உங்கள் சாதனத்தின் செயல்திறனுக்கோ செயல்பாட்டிற்கோ இடையூறு விளைவிக்கக்கூடும்."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"செயலில் உள்ள அழைப்புகளை நிர்வகித்தல்"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"உங்கள் சாதனத்தில், செயலில் உள்ள அழைப்புகள் குறித்த விவரங்களைப் பார்க்கவும் அந்த அழைப்புகளை நிர்வகிக்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index f9e0934..b4d3380 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. యాప్ మీ డివైజ్‌కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార సందేశాలను ఫార్వర్డ్ చేయడం"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార సందేశాలను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్‌కు కట్టుబడి ఉండటానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"సెల్ ప్రసార సందేశాలను చదవడం"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్‌లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్‌లను చదవడం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c23cf2b..abda062 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB)"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"อนุญาตให้แอปเชื่อมโยงกับโมดูลการส่งข้อมูลเตือนภัยทางมือถือ (CB) เพื่อส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ทันทีที่ได้รับ ระบบจะส่งการแจ้งเตือนจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในบางตำแหน่งเพื่อแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจรบกวนประสิทธิภาพหรือการทำงานของอุปกรณ์เมื่อได้รับการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในกรณีฉุกเฉิน"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"จัดการสายที่สนทนา"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"อนุญาตแอปเพื่อดูรายละเอียดเกี่ยวกับสายที่สนทนาอยู่บนโทรศัพท์และเพื่อควบคุมสายสนทนาเหล่านี้"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"อ่านฟีดข้อมูลที่สมัครไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8a6ad7e..286d28d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng MMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Magpasa ng mga mensahe ng cell broadcast"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Nagbibigay-daan sa app na mag-bind sa module ng cell broadcast para makapagpasa ng mga mensahe ng cell broadcast pagkatanggap sa mga ito. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon para balaan ka tungkol sa mga emergency na sitwasyon. Posibleng makasagabal ang mga nakakahamak na app sa performance o pagpapatakbo ng iyong device kapag nakatanggap ito ng emergency na cell broadcast."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Pamahalaan ang mga kasalukuyang tawag"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Pinapayagan ang app na makita ang mga detalye tungkol sa mga kasalukuyang tawag sa iyong device at kontrolin ang mga tawag na ito."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"basahin ang mga mensahe ng cell broadcast"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Binibigyang-daan ang app na magbasa ng mga mensahe ng cell broadcast na natanggap ng iyong device. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon upang balaan ka tungkol sa mga emergency na sitwasyon. Maaaring makaabala ang nakakahamak na apps sa performance o pagpapatakbo ng iyong device kapag nakatanggap ng emergency na cell broadcast."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"magbasa ng mga na-subscribe na feed"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d31d7e9..96c15b1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Hücre yayını mesajlarını yönlendirme"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Uygulamanın hücre yayını mesajları geldiğinde bunları yönlendirmek için hücre yayını modülüne bağlanmasına izin verir. Hücre yayını uyarıları bazı konumlarda acil durumlar hakkında sizi uyarmak için kullanılır. Zararlı uygulamalar acil durum hücre yayını alındığında cihazınızın performansını ve çalışmasını olumsuz etkileyebilir."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"hücre yayını mesajlarını oku"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abone olunan yayınları okuma"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 2352584..8511edc 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -359,6 +359,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Дозволяє програмі отримувати й обробляти MMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Переадресувати повідомлення Cell Broadcast"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволяє додатку зв\'язуватися з модулем Cell Broadcast, щоб переадресувати відповідні вхідні повідомлення. У деяких місцеположеннях сповіщення Cell Broadcast надсилаються для попередження про надзвичайні ситуації. Після повідомлення Cell Broadcast шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читати широкомовні повідомлення мережі"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читати підписані канали"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 68572d8..6eabc7b 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"‏ایپ کو MMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"سیل کے نشریاتی پیغامات فارورڈ کریں"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"سیل کی نشریاتی پیغامات کے موصول ہوتے ہی فارورڈ کرنے کے لیے ایپ کو سیل کے نشریاتی ماڈیول میں پابندی لگانے کی اجازت دیں۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل براڈ کاسٹ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں مداخلت کر سکتی ہیں۔"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"سیل کے نشریاتی پیغامات پڑھیں"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"سبسکرائب کردہ فیڈز پڑھیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 423669d..00f2215 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Ilovaga MMS xabarlarini qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Aholini ogohlantirish xabarlarini uzatish"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Qabul qilingan aholini ogohlantirish xabarlarini shu holicha uzatish uchun ilovani aholini ogohlantirish moduliga bogʻlash imkonini beradi. Ilovaga ayrim mamlakatlarda aholini favqulodda vaziyatlarda ogohlantirish uchun yuboriladigan tarqatma xabarlarni oʻqish uchun ruxsat beradi. Zararli dasturlar bunday xabarlar kelayotgan qurilmaning ishlashiga xalaqit qilishi mumkin."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Amaldagi chaqiruvlarni boshqarish"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ilovaga qurilmangizdagi amaldagi chaqiruv tafsilotlarini koʻrish va uni boshqarish huquqini beradi."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"uyali tarmoq operatori xabarlarini o‘qish"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ilovaga qurilmangiz tomonidan qabul qilingan uyali tarmoq operatori xabarlarini o‘qish uchun ruxsat beradi. Uyali tarmoq operatorining ogohlantiruvchi xabarlari ba’zi manzillarga favqulodda holatlar haqida ogohlantirish uchun jo‘natiladi. Zararli ilovalar uyali tarmoq orqali favqulodda xabar qabul qilinganda qurilmangizning ish faoliyati yoki amallariga xalaqit qilishi mumkin"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"obunalarni o‘qish"</string>
@@ -1773,7 +1775,7 @@
     <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Yangi PIN kodni tasdiqlash"</string>
     <string name="restr_pin_create_pin" msgid="917067613896366033">"Cheklovlarni o‘zgartirish uchun PIN-kod yaratish"</string>
     <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PIN-kod mos kelmadi. Qayta urinib ko‘ring."</string>
-    <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod kamida 4 ta raqamdan iborat bo‘lishi shart."</string>
+    <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod juda qisqa, kamida 4 ta raqam kiriting."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring</item>
       <item quantity="one">1 soniyadan so‘ng qayta urinib ko‘ring</item>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7533196..8b27cd0 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Chuyển tiếp tin nhắn truyền phát trên di động"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Cho phép ứng dụng liên kết với mô-đun truyền phát trên di động để chuyển tiếp tin nhắn truyền phát trên di động ngay khi nhận được. Ở một số vị trí, thông báo truyền phát trên di động sẽ được gửi nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị khi nhận được tin nhắn truyền phát trên di động lúc khẩn cấp."</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"đọc tin nhắn quảng bá"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Cho phép ứng dụng đọc tin nhắn quảng bá mà thiết bị của bạn nhận được. Tin nhắn quảng bá cảnh báo được gửi ở một số địa điểm nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể gây ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị của bạn khi nhận được tin nhắn quảng bá khẩn cấp."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 811992e..9826dfb 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"允许该应用接收和处理彩信。这就意味着,该应用可能会监视发送到您设备的彩信,或删除发送到您设备的彩信而不向您显示。"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"转发小区广播消息"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允许应用绑定到小区广播模块,以便及时转发收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您的设备收到紧急小区广播时干扰设备的性能或操作。"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"读取小区广播消息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"读取订阅的供稿"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 25807ca..33196c82 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理 MMS 訊息。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉寄區域廣播訊息"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以在收到區域廣播訊息時轉寄訊息。在某些地點,系統會發出區域廣播通知,提示您有緊急狀況發生。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"管理正在進行的通話"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"允許應用程式查看裝置上正在進行的通話詳情並控制通話。"</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱的資訊提供"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 238a890..a034f0b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -353,6 +353,10 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理多媒體訊息。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉送區域廣播訊息"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以便轉送收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
+    <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+    <skip />
+    <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+    <skip />
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱資訊提供"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6a23502..67eb874 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -353,6 +353,8 @@
     <string name="permdesc_receiveMms" msgid="958102423732219710">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-MMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
     <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Dlulisela imilayezo yokusakaza kweselula"</string>
     <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ivumela uhlelo lokusebenza ukuthi luboshezelwe kumojuli yokusakaza kweselula ukuze kudluliselwe imilayezo yokusakaza yeselula njengoba itholwa. Izexwayiso zokusakaza kweselula zilethwa kwezinye izindawo ukuze zikuxwayise ngezimo zesimo esiphuthumayo. Izinhlelo zokusebenza ezinobungozi zingaphazamisa ngokusebenza noma ukusetshenziswa kwedivayisi yakho uma ukusakaza kweselula kwesimo esiphuthumayo kwamukelwa."</string>
+    <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Phatha amakholi aqhubekayo"</string>
+    <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ivumela uhlelo lokusebenza ukubona imininingwane emayelana namakholi aqhubekayo kudivayisi yakho nokulawula lamakholi."</string>
     <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"funda imilayezo yokusakaza yeselula"</string>
     <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ivumela uhlelo lokusebenza ukufunda imilayezo yokusakaza yeselula etholwe idivayisi yakho. Izaziso zokusakaza zeselula zilethwa kwezinye izindawo ukukuxwayisa ngezimo ezisheshayo. Izinhlelo zokusebenza ezingalungile zingaphazamisana nokusebenza noma umsebenzi wedivayisi yakho uma ukusakaza kweselula kwesimo esisheshayo kutholwa."</string>
     <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"funda izifunzo ezikhokhelwayo"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 05db741..4fd8ef6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -480,7 +480,7 @@
     <dimen name="notification_inbox_item_top_padding">5dp</dimen>
 
     <!-- Size of the feedback indicator for notifications -->
-    <dimen name="notification_feedback_size">14dp</dimen>
+    <dimen name="notification_feedback_size">16dp</dimen>
 
     <!-- Size of the profile badge for notifications -->
     <dimen name="notification_badge_size">12dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 611808d..88a78a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1436,6 +1436,10 @@
   <java-symbol type="drawable" name="ic_mic" />
   <java-symbol type="drawable" name="ic_alert_window_layer" />
   <java-symbol type="drawable" name="ic_feedback_indicator" />
+  <java-symbol type="drawable" name="ic_feedback_alerted" />
+  <java-symbol type="drawable" name="ic_feedback_silenced" />
+  <java-symbol type="drawable" name="ic_feedback_uprank" />
+  <java-symbol type="drawable" name="ic_feedback_downrank" />
 
   <java-symbol type="drawable" name="ic_account_circle" />
   <java-symbol type="color" name="user_icon_1" />
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index b077ea3..1d9d9e8 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -21,6 +21,7 @@
 import android.os.BatteryStats;
 import android.os.BatteryUsageStats;
 import android.os.Process;
+import android.os.SystemBatteryConsumer;
 import android.os.UidBatteryConsumer;
 import android.os.UserHandle;
 
@@ -154,6 +155,15 @@
             return;
         }
 
+        if (requestedBatteryConsumer == null) {
+            for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) {
+                if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
+                    requestedBatteryConsumer = consumer;
+                    break;
+                }
+            }
+        }
+
         mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
                 context.getPackageManager(), requestedBatterySipper);
         long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy();
@@ -185,8 +195,14 @@
                 requestedBatterySipper.cpuPowerMah, totalCpuPowerMah);
         addEntry("System services", EntryType.POWER,
                 requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
-        addEntry("Usage", EntryType.POWER,
-                requestedBatterySipper.usagePowerMah, totalUsagePowerMah);
+        if (requestedBatteryConsumer != null) {
+            addEntry("Usage", EntryType.POWER,
+                    requestedBatteryConsumer.getConsumedPower(
+                            BatteryConsumer.POWER_COMPONENT_USAGE), totalUsagePowerMah);
+        } else {
+            addEntry("Usage (sipper)", EntryType.POWER,
+                    requestedBatterySipper.usagePowerMah, totalUsagePowerMah);
+        }
         addEntry("Wake lock", EntryType.POWER,
                 requestedBatterySipper.wakeLockPowerMah, totalWakeLockPowerMah);
         addEntry("Mobile radio", EntryType.POWER,
@@ -295,6 +311,8 @@
             return BatterySipper.DrainType.APP + "|"
                     + UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|"
                     + ((UidBatteryConsumer) consumer).getUid();
+        } else if (consumer instanceof SystemBatteryConsumer) {
+            return ((SystemBatteryConsumer) consumer).getDrainType() + "|0|0";
         } else {
             return "";
         }
diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS
new file mode 100644
index 0000000..bd7da0c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/OWNERS
@@ -0,0 +1 @@
+per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/app/activity/OWNERS b/core/tests/coretests/src/android/app/activity/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/activity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/app/appsearch/OWNERS b/core/tests/coretests/src/android/app/appsearch/OWNERS
new file mode 100644
index 0000000..24f6b0b
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
index e03cea3..879aa09 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
@@ -16,28 +16,54 @@
 
 package android.app.appsearch;
 
+import static android.app.appsearch.AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES;
+import static android.app.appsearch.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.testng.Assert.expectThrows;
 
+import android.util.ArrayMap;
+
 import org.junit.Test;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
 public class SetSchemaRequestTest {
 
     @Test
-    public void testInvalidSchemaReferences() {
+    public void testInvalidSchemaReferences_fromSystemUiVisibility() {
         IllegalArgumentException expected =
                 expectThrows(
                         IllegalArgumentException.class,
                         () ->
                                 new SetSchemaRequest.Builder()
-                                        .setSchemaTypeVisibilityForSystemUi(false, "InvalidSchema")
+                                        .setSchemaTypeVisibilityForSystemUi("InvalidSchema", false)
                                         .build());
         assertThat(expected).hasMessageThat().contains("referenced, but were not added");
     }
 
     @Test
-    public void testSchemaTypeVisibilityForSystemUi_Visible() {
+    public void testInvalidSchemaReferences_fromPackageVisibility() {
+        IllegalArgumentException expected =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new SetSchemaRequest.Builder()
+                                        .setSchemaTypeVisibilityForPackage(
+                                                "InvalidSchema",
+                                                /*visible=*/ true,
+                                                new PackageIdentifier(
+                                                        "com.foo.package",
+                                                        /*certificate=*/ new byte[] {}))
+                                        .build());
+        assertThat(expected).hasMessageThat().contains("referenced, but were not added");
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForSystemUi_visible() {
         AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
 
         // By default, the schema is visible.
@@ -47,19 +73,106 @@
         request =
                 new SetSchemaRequest.Builder()
                         .addSchema(schema)
-                        .setSchemaTypeVisibilityForSystemUi(true, "Schema")
+                        .setSchemaTypeVisibilityForSystemUi("Schema", true)
                         .build();
         assertThat(request.getSchemasNotPlatformSurfaceable()).isEmpty();
     }
 
     @Test
-    public void testSchemaTypeVisibilityForSystemUi_NotVisible() {
+    public void testSchemaTypeVisibilityForSystemUi_notVisible() {
         AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
         SetSchemaRequest request =
                 new SetSchemaRequest.Builder()
                         .addSchema(schema)
-                        .setSchemaTypeVisibilityForSystemUi(false, "Schema")
+                        .setSchemaTypeVisibilityForSystemUi("Schema", false)
                         .build();
         assertThat(request.getSchemasNotPlatformSurfaceable()).containsExactly("Schema");
     }
+
+    @Test
+    public void testSchemaTypeVisibilityForPackage_visible() {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+        // By default, the schema is not visible.
+        SetSchemaRequest request = new SetSchemaRequest.Builder().addSchema(schema).build();
+        assertThat(request.getSchemasPackageAccessible()).isEmpty();
+
+        PackageIdentifier packageIdentifier =
+                new PackageIdentifier("com.package.foo", new byte[] {100});
+        Map<String, Set<PackageIdentifier>> expectedPackageVisibleMap = new ArrayMap<>();
+        expectedPackageVisibleMap.put("Schema", Collections.singleton(packageIdentifier));
+
+        request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema", /*visible=*/ true, packageIdentifier)
+                        .build();
+        assertThat(request.getSchemasPackageAccessible())
+                .containsExactlyEntriesIn(expectedPackageVisibleMap);
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForPackage_notVisible() {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+        SetSchemaRequest request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema",
+                                /*visible=*/ false,
+                                new PackageIdentifier(
+                                        "com.package.foo", /*certificate=*/ new byte[] {}))
+                        .build();
+        assertThat(request.getSchemasPackageAccessible()).isEmpty();
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForPackage_deduped() throws Exception {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+        PackageIdentifier packageIdentifier =
+                new PackageIdentifier("com.package.foo", new byte[] {100});
+        Map<String, Set<PackageIdentifier>> expectedPackageVisibleMap = new ArrayMap<>();
+        expectedPackageVisibleMap.put("Schema", Collections.singleton(packageIdentifier));
+
+        SetSchemaRequest request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        // Set it visible for "Schema"
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema", /*visible=*/ true, packageIdentifier)
+                        // Set it visible for "Schema" again, which should be a no-op
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema", /*visible=*/ true, packageIdentifier)
+                        .build();
+        assertThat(request.getSchemasPackageAccessible())
+                .containsExactlyEntriesIn(expectedPackageVisibleMap);
+    }
+
+    @Test
+    public void testSchemaTypeVisibilityForPackage_removed() throws Exception {
+        AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+        SetSchemaRequest request =
+                new SetSchemaRequest.Builder()
+                        .addSchema(schema)
+                        // First set it as visible
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema",
+                                /*visible=*/ true,
+                                new PackageIdentifier(
+                                        "com.package.foo", /*certificate=*/ new byte[] {100}))
+                        // Then make it not visible
+                        .setSchemaTypeVisibilityForPackage(
+                                "Schema",
+                                /*visible=*/ false,
+                                new PackageIdentifier(
+                                        "com.package.foo", /*certificate=*/ new byte[] {100}))
+                        .build();
+
+        // Nothing should be visible.
+        assertThat(request.getSchemasPackageAccessible()).isEmpty();
+    }
 }
diff --git a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
index 7552ec4..1d83003 100644
--- a/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
+++ b/core/tests/coretests/src/android/app/people/PeopleSpaceTileTest.java
@@ -25,7 +25,6 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
-import android.app.Notification;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
@@ -35,8 +34,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
-import android.os.UserHandle;
-import android.service.notification.StatusBarNotification;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -186,17 +183,34 @@
     }
 
     @Test
-    public void testNotification() {
-        Notification notification = new Notification.Builder(mContext, "test").build();
-        StatusBarNotification sbn = new StatusBarNotification("pkg" /* pkg */, "pkg" /* opPkg */,
-                1 /* id */, "" /* tag */, 0 /* uid */, 0 /* initialPid */, 0 /* score */,
-                notification, UserHandle.CURRENT, 0 /* postTime */);
+    public void testNotificationKey() {
         PeopleSpaceTile tile = new PeopleSpaceTile
                 .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
-                .setNotification(sbn)
+                .setNotificationKey("test")
                 .build();
 
-        assertThat(tile.getNotification()).isEqualTo(sbn);
+        assertThat(tile.getNotificationKey()).isEqualTo("test");
+    }
+
+    @Test
+    public void testNotificationContent() {
+        PeopleSpaceTile tile = new PeopleSpaceTile
+                .Builder(new ShortcutInfo.Builder(mContext, "123").build(), mLauncherApps)
+                .setNotificationContent("test")
+                .build();
+
+        assertThat(tile.getNotificationContent()).isEqualTo("test");
+    }
+
+    @Test
+    public void testNotificationDataUri() {
+        PeopleSpaceTile tile =
+                new PeopleSpaceTile.Builder(new ShortcutInfo.Builder(mContext, "123").build(),
+                        mLauncherApps)
+                .setNotificationDataUri(Uri.parse("test"))
+                .build();
+
+        assertThat(tile.getNotificationDataUri()).isEqualTo(Uri.parse("test"));
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/app/servertransaction/OWNERS b/core/tests/coretests/src/android/app/servertransaction/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/servertransaction/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
new file mode 100644
index 0000000..911efb2
--- /dev/null
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -0,0 +1 @@
+per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/mockingcoretests/src/android/app/activity/OWNERS b/core/tests/mockingcoretests/src/android/app/activity/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/app/activity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS
index c3fb6f8..a8a3631 100644
--- a/graphics/java/android/graphics/OWNERS
+++ b/graphics/java/android/graphics/OWNERS
@@ -6,3 +6,6 @@
 sumir@google.com
 
 per-file BLASTBufferQueue.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file FontFamily.java = file:fonts/OWNERS
+per-file FontListParser.java = file:fonts/OWNERS
+per-file Typeface.java = file:fonts/OWNERS
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 001ebac..117828d 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -858,9 +858,10 @@
      * be blurred when this RenderNode is drawn into the destination.
      * @param renderEffect to be applied to the RenderNode. Passing null clears all previously
      *          configured RenderEffects
+     * @return True if the value changed, false if the new value was the same as the previous value.
      */
-    public void setRenderEffect(@Nullable RenderEffect renderEffect) {
-        nSetRenderEffect(mNativeRenderNode,
+    public boolean setRenderEffect(@Nullable RenderEffect renderEffect) {
+        return nSetRenderEffect(mNativeRenderNode,
                 renderEffect != null ? renderEffect.getNativeInstance() : 0);
     }
 
@@ -1670,7 +1671,7 @@
     private static native boolean nSetAlpha(long renderNode, float alpha);
 
     @CriticalNative
-    private static native void nSetRenderEffect(long renderNode, long renderEffect);
+    private static native boolean nSetRenderEffect(long renderNode, long renderEffect);
 
     @CriticalNative
     private static native boolean nSetHasOverlappingRendering(long renderNode,
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index ad87025..ea21eb9 100644
--- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<com.android.wm.shell.splitscreen.DividerView
+<com.android.wm.shell.legacysplitscreen.DividerView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_height="match_parent"
         android:layout_width="match_parent">
@@ -24,15 +24,15 @@
         android:id="@+id/docked_divider_background"
         android:background="@color/docked_divider_background"/>
 
-    <com.android.wm.shell.splitscreen.MinimizedDockShadow
+    <com.android.wm.shell.legacysplitscreen.MinimizedDockShadow
         style="@style/DockedDividerMinimizedShadow"
         android:id="@+id/minimized_dock_shadow"
         android:alpha="0"/>">
 
-    <com.android.wm.shell.splitscreen.DividerHandleView
+    <com.android.wm.shell.legacysplitscreen.DividerHandleView
         style="@style/DockedDividerHandle"
         android:id="@+id/docked_divider_handle"
         android:contentDescription="@string/accessibility_divider"
         android:background="@null"/>
 
-</com.android.wm.shell.splitscreen.DividerView>
+</com.android.wm.shell.legacysplitscreen.DividerView>
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index db9e1af9..4070829 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,12 +1,6 @@
 {
   "version": "1.0.0",
   "messages": {
-    "-1993693214": {
-      "message": "Letterbox Task Changed: #%d",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
-    },
     "-1683614271": {
       "message": "Existing task: id=%d component=%s",
       "level": "VERBOSE",
@@ -37,6 +31,12 @@
       "group": "WM_SHELL_DRAG_AND_DROP",
       "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
     },
+    "-1362429294": {
+      "message": "%s onTaskAppeared Primary taskId=%d",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+    },
     "-1340279385": {
       "message": "Remove listener=%s",
       "level": "VERBOSE",
@@ -73,12 +73,6 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     },
-    "-842742255": {
-      "message": "%s onTaskAppeared unknown taskId=%d winMode=%d",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
-    },
     "-742394458": {
       "message": "pair task1=%d task2=%d in AppPair=%s",
       "level": "VERBOSE",
@@ -91,17 +85,11 @@
       "group": "WM_SHELL_DRAG_AND_DROP",
       "at": "com\/android\/wm\/shell\/draganddrop\/DragLayout.java"
     },
-    "-679492476": {
-      "message": "%s onTaskAppeared Primary taskId=%d",
+    "-298656957": {
+      "message": "%s onTaskAppeared unknown taskId=%d winMode=%d",
       "level": "VERBOSE",
       "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
-    },
-    "-342975160": {
-      "message": "Letterbox Task Vanished: #%d",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
+      "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
     },
     "-234284913": {
       "message": "unpair taskId=%d pair=%s",
@@ -115,12 +103,6 @@
       "group": "WM_SHELL_TRANSITIONS",
       "at": "com\/android\/wm\/shell\/Transitions.java"
     },
-    "154313206": {
-      "message": "%s onTaskAppeared Secondary taskId=%d",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
-    },
     "157713005": {
       "message": "Task info changed taskId=%d",
       "level": "VERBOSE",
@@ -139,6 +121,12 @@
       "group": "WM_SHELL_DRAG_AND_DROP",
       "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
     },
+    "473543554": {
+      "message": "%s onTaskAppeared Supported",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+    },
     "481673835": {
       "message": "addListenerForTaskId taskId=%s",
       "level": "VERBOSE",
@@ -175,6 +163,12 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     },
+    "982027396": {
+      "message": "%s onTaskAppeared Secondary taskId=%d",
+      "level": "VERBOSE",
+      "group": "WM_SHELL_TASK_ORG",
+      "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+    },
     "1079041527": {
       "message": "incrementPool size=%d",
       "level": "VERBOSE",
@@ -199,12 +193,6 @@
       "group": "WM_SHELL_DRAG_AND_DROP",
       "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
     },
-    "1885882094": {
-      "message": "Letterbox Task Appeared: #%d",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
-    },
     "1891981945": {
       "message": "release entry.taskId=%s listener=%s size=%d",
       "level": "VERBOSE",
@@ -228,12 +216,6 @@
       "level": "VERBOSE",
       "group": "WM_SHELL_DRAG_AND_DROP",
       "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
-    },
-    "2135461748": {
-      "message": "%s onTaskAppeared Supported",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
     }
   },
   "groups": {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
new file mode 100644
index 0000000..f741a42
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell;
+
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+import android.window.DisplayAreaInfo;
+import android.window.DisplayAreaOrganizer;
+
+import androidx.annotation.NonNull;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/** Display area organizer for the root/default TaskDisplayAreas */
+public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
+
+    private static final String TAG = RootTaskDisplayAreaOrganizer.class.getSimpleName();
+
+    // Display area info. mapped by displayIds.
+    private final SparseArray<DisplayAreaInfo> mDisplayAreasInfo = new SparseArray<>();
+    // Display area leashes. mapped by displayIds.
+    private final SparseArray<SurfaceControl> mLeashes = new SparseArray<>();
+
+    private final SparseArray<ArrayList<RootTaskDisplayAreaListener>> mListeners =
+            new SparseArray<>();
+
+    public RootTaskDisplayAreaOrganizer(Executor executor) {
+        super(executor);
+        registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
+    }
+
+    public void registerListener(int displayId, RootTaskDisplayAreaListener listener) {
+        ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+        if (listeners == null) {
+            listeners = new ArrayList<>();
+            mListeners.put(displayId, listeners);
+        }
+
+        listeners.add(listener);
+
+        final DisplayAreaInfo info = mDisplayAreasInfo.get(displayId);
+        if (info != null) {
+            listener.onDisplayAreaAppeared(info);
+        }
+    }
+
+    public void unregisterListener(RootTaskDisplayAreaListener listener) {
+        for (int i = mListeners.size() - 1; i >= 0; --i) {
+            final List<RootTaskDisplayAreaListener> listeners = mListeners.valueAt(i);
+            if (listeners == null) continue;
+            listeners.remove(listener);
+        }
+    }
+
+    public void attachToDisplayArea(int displayId, SurfaceControl.Builder b) {
+        final SurfaceControl sc = mLeashes.get(displayId);
+        b.setParent(sc);
+    }
+
+    @Override
+    public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
+            @NonNull SurfaceControl leash) {
+        if (displayAreaInfo.featureId != FEATURE_DEFAULT_TASK_CONTAINER) {
+            throw new IllegalArgumentException(
+                    "Unknown feature: " + displayAreaInfo.featureId
+                            + "displayAreaInfo:" + displayAreaInfo);
+        }
+
+        final int displayId = displayAreaInfo.displayId;
+        if (mDisplayAreasInfo.get(displayId) != null) {
+            throw new IllegalArgumentException(
+                    "Duplicate DA for displayId: " + displayId
+                            + " displayAreaInfo:" + displayAreaInfo
+                            + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+        }
+
+        mDisplayAreasInfo.put(displayId, displayAreaInfo);
+
+        ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+        if (listeners != null) {
+            for (int i = listeners.size() - 1; i >= 0; --i) {
+                listeners.get(i).onDisplayAreaAppeared(displayAreaInfo);
+            }
+        }
+    }
+
+    @Override
+    public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
+        final int displayId = displayAreaInfo.displayId;
+        if (mDisplayAreasInfo.get(displayId) == null) {
+            throw new IllegalArgumentException(
+                    "onDisplayAreaVanished() Unknown DA displayId: " + displayId
+                            + " displayAreaInfo:" + displayAreaInfo
+                            + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+        }
+
+        mDisplayAreasInfo.remove(displayId);
+
+        ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+        if (listeners != null) {
+            for (int i = listeners.size() - 1; i >= 0; --i) {
+                listeners.get(i).onDisplayAreaVanished(displayAreaInfo);
+            }
+        }
+    }
+
+    @Override
+    public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) {
+        final int displayId = displayAreaInfo.displayId;
+        if (mDisplayAreasInfo.get(displayId) == null) {
+            throw new IllegalArgumentException(
+                    "onDisplayAreaInfoChanged() Unknown DA displayId: " + displayId
+                            + " displayAreaInfo:" + displayAreaInfo
+                            + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+        }
+
+        mDisplayAreasInfo.put(displayId, displayAreaInfo);
+
+        ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+        if (listeners != null) {
+            for (int i = listeners.size() - 1; i >= 0; --i) {
+                listeners.get(i).onDisplayAreaInfoChanged(displayAreaInfo);
+            }
+        }
+    }
+
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        final String childPrefix = innerPrefix + "  ";
+        pw.println(prefix + this);
+    }
+
+    @Override
+    public String toString() {
+        return TAG + "#" + mDisplayAreasInfo.size();
+    }
+
+    /** Callbacks for when root task display areas change. */
+    public interface RootTaskDisplayAreaListener {
+        default void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) {
+        }
+
+        default void onDisplayAreaVanished(DisplayAreaInfo displayAreaInfo) {
+        }
+
+        default void onDisplayAreaInfoChanged(DisplayAreaInfo displayAreaInfo) {
+        }
+
+        default void dump(@NonNull PrintWriter pw, String prefix) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
index 2085042..2f2168f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
@@ -21,7 +21,7 @@
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.PrintWriter;
 import java.util.Optional;
@@ -33,7 +33,7 @@
  */
 public final class ShellCommandHandler {
 
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
     private final Optional<Pip> mPipOptional;
     private final Optional<OneHanded> mOneHandedOptional;
     private final Optional<HideDisplayCutout> mHideDisplayCutout;
@@ -42,13 +42,13 @@
 
     public ShellCommandHandler(
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<Pip> pipOptional,
             Optional<OneHanded> oneHandedOptional,
             Optional<HideDisplayCutout> hideDisplayCutout,
             Optional<AppPairs> appPairsOptional) {
         mShellTaskOrganizer = shellTaskOrganizer;
-        mSplitScreenOptional = splitScreenOptional;
+        mLegacySplitScreenOptional = legacySplitScreenOptional;
         mPipOptional = pipOptional;
         mOneHandedOptional = oneHandedOptional;
         mHideDisplayCutout = hideDisplayCutout;
@@ -62,7 +62,7 @@
         pw.println();
         pw.println();
         mPipOptional.ifPresent(pip -> pip.dump(pw));
-        mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
+        mLegacySplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
         mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
         mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
         pw.println();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
index f895603..f4c617e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
@@ -22,7 +22,7 @@
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.annotations.ExternalThread;
 import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -34,7 +34,7 @@
     private final DisplayImeController mDisplayImeController;
     private final DragAndDropController mDragAndDropController;
     private final ShellTaskOrganizer mShellTaskOrganizer;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
     private final Optional<AppPairs> mAppPairsOptional;
     private final FullscreenTaskListener mFullscreenTaskListener;
     private final Transitions mTransitions;
@@ -42,14 +42,14 @@
     public ShellInit(DisplayImeController displayImeController,
             DragAndDropController dragAndDropController,
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<AppPairs> appPairsOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Transitions transitions) {
         mDisplayImeController = displayImeController;
         mDragAndDropController = dragAndDropController;
         mShellTaskOrganizer = shellTaskOrganizer;
-        mSplitScreenOptional = splitScreenOptional;
+        mLegacySplitScreenOptional = legacySplitScreenOptional;
         mAppPairsOptional = appPairsOptional;
         mFullscreenTaskListener = fullscreenTaskListener;
         mTransitions = transitions;
@@ -67,7 +67,7 @@
 
         mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
         // Bind the splitscreen impl to the drag drop controller
-        mDragAndDropController.setSplitScreenController(mSplitScreenOptional);
+        mDragAndDropController.setSplitScreenController(mLegacySplitScreenOptional);
 
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             mTransitions.register(mShellTaskOrganizer);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index cfbf845..9754f51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -96,7 +96,7 @@
         mTaskInfo2 = task2;
         mSplitLayout = new SplitLayout(
                 mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
-                mRootTaskInfo.configuration, this, mRootTaskLeash);
+                mRootTaskInfo.configuration, this, b -> b.setParent(mRootTaskLeash));
 
         final WindowContainerToken token1 = task1.token;
         final WindowContainerToken token2 = task2.token;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index e1a94b0..6b9bf2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -57,10 +57,12 @@
     private int mDividePosition;
 
     public SplitLayout(Context context, Configuration configuration,
-            LayoutChangeListener layoutChangeListener, SurfaceControl rootLeash) {
+            LayoutChangeListener layoutChangeListener,
+            SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks) {
         mContext = context.createConfigurationContext(configuration);
         mLayoutChangeListener = layoutChangeListener;
-        mSplitWindowManager = new SplitWindowManager(mContext, configuration, rootLeash);
+        mSplitWindowManager = new SplitWindowManager(
+                mContext, configuration, parentContainerCallbacks);
 
         mDividerWindowWidth = context.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index e412198..238caef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -51,10 +51,17 @@
 
     private Context mContext;
     private SurfaceControlViewHost mViewHost;
+    final private ParentContainerCallbacks mParentContainerCallbacks;
 
-    public SplitWindowManager(Context context, Configuration config, SurfaceControl rootSurface) {
-        super(config, rootSurface, null /* hostInputToken */);
+    public interface ParentContainerCallbacks {
+        void attachToParentSurface(SurfaceControl.Builder b);
+    }
+
+    public SplitWindowManager(Context context, Configuration config,
+            ParentContainerCallbacks parentContainerCallbacks) {
+        super(config, null /* rootSurface */, null /* hostInputToken */);
         mContext = context.createConfigurationContext(config);
+        mParentContainerCallbacks = parentContainerCallbacks;
     }
 
     @Override
@@ -73,6 +80,11 @@
         mContext = mContext.createConfigurationContext(configuration);
     }
 
+    @Override
+    protected void attachToParentSurface(SurfaceControl.Builder b) {
+        mParentContainerCallbacks.attachToParentSurface(b);
+    }
+
     /** Inflates {@link DividerView} on to the root surface. */
     void init(SplitLayout splitLayout) {
         if (mViewHost == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index a89c8bb..8ae6679 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -52,7 +52,7 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -66,7 +66,7 @@
 
     private final Context mContext;
     private final DisplayController mDisplayController;
-    private SplitScreen mSplitScreen;
+    private LegacySplitScreen mLegacySplitScreen;
 
     private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>();
     private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -77,8 +77,8 @@
         mDisplayController.addDisplayWindowListener(this);
     }
 
-    public void setSplitScreenController(Optional<SplitScreen> splitscreen) {
-        mSplitScreen = splitscreen.orElse(null);
+    public void setSplitScreenController(Optional<LegacySplitScreen> splitscreen) {
+        mLegacySplitScreen = splitscreen.orElse(null);
     }
 
     @Override
@@ -104,7 +104,7 @@
                 R.layout.global_drop_target, null);
         rootView.setOnDragListener(this);
         rootView.setVisibility(View.INVISIBLE);
-        DragLayout dragLayout = new DragLayout(context, mSplitScreen);
+        DragLayout dragLayout = new DragLayout(context, mLegacySplitScreen);
         rootView.addView(dragLayout,
                 new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
         try {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 7b3b5db..4043d0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -37,7 +37,6 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
 import android.app.PendingIntent;
 import android.app.WindowConfiguration;
 import android.content.ActivityNotFoundException;
@@ -60,7 +59,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -78,22 +77,22 @@
     private final Context mContext;
     private final ActivityTaskManager mActivityTaskManager;
     private final Starter mStarter;
-    private final SplitScreen mSplitScreen;
+    private final LegacySplitScreen mLegacySplitScreen;
     private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
 
     private DragSession mSession;
 
-    public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
-        this(context, ActivityTaskManager.getInstance(), splitScreen,
-                new DefaultStarter(context, splitScreen));
+    public DragAndDropPolicy(Context context, LegacySplitScreen legacySplitScreen) {
+        this(context, ActivityTaskManager.getInstance(), legacySplitScreen,
+                new DefaultStarter(context, legacySplitScreen));
     }
 
     @VisibleForTesting
     DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager,
-            SplitScreen splitScreen, Starter starter) {
+            LegacySplitScreen legacySplitScreen, Starter starter) {
         mContext = context;
         mActivityTaskManager = activityTaskManager;
-        mSplitScreen = splitScreen;
+        mLegacySplitScreen = legacySplitScreen;
         mStarter = starter;
     }
 
@@ -151,13 +150,13 @@
                         new Rect(w / 2, 0, w, h)));
             }
         } else if (mSession.dragItemSupportsSplitscreen
-                && mSplitScreen != null
-                && mSplitScreen.isDividerVisible()) {
+                && mLegacySplitScreen != null
+                && mLegacySplitScreen.isDividerVisible()) {
             // Already split, allow replacing existing split task
             // TODO(b/169894807): For now, only allow replacing the non-primary task until we have
             //                    split pairs
             final Rect secondarySplitRawBounds =
-                    mSplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds();
+                    mLegacySplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds();
             final Rect secondarySplitBounds = new Rect(secondarySplitRawBounds);
             secondarySplitBounds.intersect(new Rect(l, t, l + iw, t + ih));
             if (isVerticalSplit) {
@@ -212,14 +211,14 @@
 
         boolean deferAppLaunchUntilSplit = false;
         if (target.type == TYPE_FULLSCREEN) {
-            if (mSplitScreen != null && mSplitScreen.isDividerVisible()) {
+            if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
                 // If in split, remove split and launch fullscreen
                 mStarter.exitSplitScreen(mSession.runningTaskId);
             } else {
                 // Not in split, fall through to launch
             }
         } else {
-            if (mSplitScreen != null && mSplitScreen.isDividerVisible()) {
+            if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
                 // Split is already visible, just replace the task
                 // TODO(b/169894807): Since we only allow replacing the non-primary target above
                 //                    just fall through and start the activity
@@ -250,12 +249,12 @@
             // into split, and we should wait for home and other tasks to be moved to
             // split-secondary before trying to launch the new secondary task.  This can be removed
             // once we have app-pairs.
-            mSplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
+            mLegacySplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
                 @Override
                 public void accept(Boolean inSplit) {
                     if (inSplit) {
                         startAppRunnable.run();
-                        mSplitScreen.unregisterInSplitScreenListener(this);
+                        mLegacySplitScreen.unregisterInSplitScreenListener(this);
                     }
                 }
             });
@@ -333,11 +332,11 @@
      */
     private static class DefaultStarter implements Starter {
         private final Context mContext;
-        private final SplitScreen mSplitScreen;
+        private final LegacySplitScreen mLegacySplitScreen;
 
-        public DefaultStarter(Context context, SplitScreen splitScreen) {
+        public DefaultStarter(Context context, LegacySplitScreen legacySplitScreen) {
             mContext = context;
-            mSplitScreen = splitScreen;
+            mLegacySplitScreen = legacySplitScreen;
         }
 
         @Override
@@ -373,12 +372,12 @@
 
         @Override
         public void enterSplitScreen(int taskId, boolean leftOrTop) {
-            mSplitScreen.splitPrimaryTask();
+            mLegacySplitScreen.splitPrimaryTask();
         }
 
         @Override
         public void exitSplitScreen(int taskId) {
-            mSplitScreen.dismissSplitToPrimaryTask();
+            mLegacySplitScreen.dismissSplitToPrimaryTask();
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 5b7531c..a56fe8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -35,7 +35,6 @@
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type;
-import android.view.animation.Interpolator;
 
 import androidx.annotation.NonNull;
 
@@ -43,10 +42,9 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.ArrayList;
-import java.util.function.Consumer;
 
 /**
  * Coordinates the visible drop targets for the current drag.
@@ -63,7 +61,7 @@
     private boolean mIsShowing;
     private boolean mHasDropped;
 
-    public DragLayout(Context context, SplitScreen splitscreen) {
+    public DragLayout(Context context, LegacySplitScreen splitscreen) {
         super(context);
         mPolicy = new DragAndDropPolicy(context, splitscreen);
         mDisplayMargin = context.getResources().getDimensionPixelSize(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
index e4e2546..b92846f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
@@ -27,6 +27,7 @@
 import com.android.wm.shell.common.DisplayController;
 
 import java.io.PrintWriter;
+import java.util.concurrent.Executor;
 
 /**
  * Manages the hide display cutout status.
@@ -51,7 +52,7 @@
      */
     @Nullable
     public static HideDisplayCutoutController create(
-            Context context, DisplayController displayController) {
+            Context context, DisplayController displayController, Executor executor) {
         // The SystemProperty is set for devices that support this feature and is used to control
         // whether to create the HideDisplayCutout instance.
         // It's defined in the device.mk (e.g. device/google/crosshatch/device.mk).
@@ -60,7 +61,7 @@
         }
 
         HideDisplayCutoutOrganizer organizer =
-                new HideDisplayCutoutOrganizer(context, displayController);
+                new HideDisplayCutoutOrganizer(context, displayController, executor);
         return new HideDisplayCutoutController(context, organizer);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
index 4e62ea6..51a35d8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
@@ -45,6 +45,7 @@
 
 import java.io.PrintWriter;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Manages the display areas of hide display cutout feature.
@@ -88,7 +89,9 @@
                 t.apply();
             };
 
-    HideDisplayCutoutOrganizer(Context context, DisplayController displayController) {
+    HideDisplayCutoutOrganizer(Context context, DisplayController displayController,
+            Executor executor) {
+        super(executor);
         mContext = context;
         mDisplayController = displayController;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
index 2cb1fff..17ca110 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
index 71710af..2c0cf59 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
 import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
@@ -37,11 +37,11 @@
 
 class DividerImeController implements DisplayImeController.ImePositionProcessor {
     private static final String TAG = "DividerImeController";
-    private static final boolean DEBUG = SplitScreenController.DEBUG;
+    private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
 
     private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
 
-    private final SplitScreenTaskListener mSplits;
+    private final LegacySplitScreenTaskListener mSplits;
     private final TransactionPool mTransactionPool;
     private final Handler mHandler;
     private final TaskOrganizer mTaskOrganizer;
@@ -93,8 +93,8 @@
     private boolean mPausedTargetAdjusted = false;
     private boolean mAdjustedWhileHidden = false;
 
-    DividerImeController(SplitScreenTaskListener splits, TransactionPool pool, Handler handler,
-            TaskOrganizer taskOrganizer) {
+    DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool,
+            Handler handler, TaskOrganizer taskOrganizer) {
         mSplits = splits;
         mTransactionPool = pool;
         mHandler = handler;
@@ -105,7 +105,7 @@
         return mSplits.mSplitScreenController.getDividerView();
     }
 
-    private SplitDisplayLayout getLayout() {
+    private LegacySplitDisplayLayout getLayout() {
         return mSplits.mSplitScreenController.getSplitLayout();
     }
 
@@ -202,7 +202,7 @@
             // Reposition the server's secondary split position so that it evaluates
             // insets properly.
             WindowContainerTransaction wct = new WindowContainerTransaction();
-            final SplitDisplayLayout splitLayout = getLayout();
+            final LegacySplitDisplayLayout splitLayout = getLayout();
             if (mTargetAdjusted) {
                 splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
                 wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
@@ -285,7 +285,7 @@
     private void onProgress(float progress, SurfaceControl.Transaction t) {
         final DividerView view = getView();
         if (mTargetAdjusted != mAdjusted && !mPaused) {
-            final SplitDisplayLayout splitLayout = getLayout();
+            final LegacySplitDisplayLayout splitLayout = getLayout();
             final float fraction = mTargetAdjusted ? progress : 1.f - progress;
             mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
             splitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
similarity index 94%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
index 23d86a0..af2ab15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 /**
  * Class to hold state of divider that needs to persist across configuration changes.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index ba07166..16c966f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
 import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
@@ -75,7 +75,7 @@
 public class DividerView extends FrameLayout implements OnTouchListener,
         OnComputeInternalInsetsListener {
     private static final String TAG = "DividerView";
-    private static final boolean DEBUG = SplitScreenController.DEBUG;
+    private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
 
     interface DividerCallbacks {
         void onDraggingStart();
@@ -137,12 +137,12 @@
     private final Rect mOtherInsetRect = new Rect();
     private final Rect mLastResizeRect = new Rect();
     private final Rect mTmpRect = new Rect();
-    private SplitScreenController mSplitScreenController;
+    private LegacySplitScreenController mSplitScreenController;
     private WindowManagerProxy mWindowManagerProxy;
     private DividerWindowManager mWindowManager;
     private VelocityTracker mVelocityTracker;
     private FlingAnimationUtils mFlingAnimationUtils;
-    private SplitDisplayLayout mSplitLayout;
+    private LegacySplitDisplayLayout mSplitLayout;
     private DividerImeController mImeController;
     private DividerCallbacks mCallback;
     private final AnimationHandler mAnimationHandler = new AnimationHandler();
@@ -156,7 +156,7 @@
     private boolean mAdjustedForIme;
     private DividerState mState;
 
-    private SplitScreenTaskListener mTiles;
+    private LegacySplitScreenTaskListener mTiles;
     boolean mFirstLayout = true;
     int mDividerPositionX;
     int mDividerPositionY;
@@ -353,10 +353,11 @@
         }
     }
 
-    void injectDependencies(SplitScreenController splitScreenController,
+    void injectDependencies(LegacySplitScreenController splitScreenController,
             DividerWindowManager windowManager, DividerState dividerState,
-            DividerCallbacks callback, SplitScreenTaskListener tiles, SplitDisplayLayout sdl,
-            DividerImeController imeController, WindowManagerProxy wmProxy) {
+            DividerCallbacks callback, LegacySplitScreenTaskListener tiles,
+            LegacySplitDisplayLayout sdl, DividerImeController imeController,
+            WindowManagerProxy wmProxy) {
         mSplitScreenController = splitScreenController;
         mWindowManager = windowManager;
         mState = dividerState;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
index 5078371..2c3ae68 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
index 7a16335..abff69c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
similarity index 95%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
index 1ef142d..ee5c9bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 
-import static com.android.wm.shell.splitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+import static com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
 
 import android.app.ActivityOptions;
 import android.content.Context;
@@ -69,7 +69,7 @@
     }
 
     ForcedResizableInfoActivityController(Context context,
-            SplitScreenController splitScreenController) {
+            LegacySplitScreenController splitScreenController) {
         mContext = context;
         splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
similarity index 97%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
index 7d5e1a8..477ec33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -40,14 +40,14 @@
  * Handles split-screen related internal display layout. In general, this represents the
  * WM-facing understanding of the splits.
  */
-public class SplitDisplayLayout {
+public class LegacySplitDisplayLayout {
     /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
      * restrict IME adjustment so that a min portion of top stack remains visible.*/
     private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
 
     private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
 
-    SplitScreenTaskListener mTiles;
+    LegacySplitScreenTaskListener mTiles;
     DisplayLayout mDisplayLayout;
     Context mContext;
 
@@ -62,7 +62,8 @@
     Rect mAdjustedPrimary = null;
     Rect mAdjustedSecondary = null;
 
-    public SplitDisplayLayout(Context ctx, DisplayLayout dl, SplitScreenTaskListener taskTiles) {
+    public LegacySplitDisplayLayout(Context ctx, DisplayLayout dl,
+            LegacySplitScreenTaskListener taskTiles) {
         mTiles = taskTiles;
         mDisplayLayout = dl;
         mContext = ctx;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
index 7c70a4efa..499a9c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import android.graphics.Rect;
 import android.window.WindowContainerToken;
@@ -29,7 +29,7 @@
  * Interface to engage split screen feature.
  */
 @ExternalThread
-public interface SplitScreen {
+public interface LegacySplitScreen {
     /** Called when keyguard showing state changed. */
     void onKeyguardVisibilityChanged(boolean isShowing);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index 6d6c761..d88696d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
@@ -65,7 +65,7 @@
 /**
  * Controls split screen feature.
  */
-public class SplitScreenController implements SplitScreen,
+public class LegacySplitScreenController implements LegacySplitScreen,
         DisplayController.OnDisplaysChangedListener {
     static final boolean DEBUG = false;
 
@@ -80,7 +80,7 @@
     private final DividerState mDividerState = new DividerState();
     private final ForcedResizableInfoActivityController mForcedResizableController;
     private final Handler mHandler;
-    private final SplitScreenTaskListener mSplits;
+    private final LegacySplitScreenTaskListener mSplits;
     private final SystemWindows mSystemWindows;
     final TransactionPool mTransactionPool;
     private final WindowManagerProxy mWindowManagerProxy;
@@ -96,12 +96,12 @@
     private DividerView mView;
 
     // Keeps track of real-time split geometry including snap positions and ime adjustments
-    private SplitDisplayLayout mSplitLayout;
+    private LegacySplitDisplayLayout mSplitLayout;
 
     // Transient: this contains the layout calculated for a new rotation requested by WM. This is
     // kept around so that we can wait for a matching configuration change and then use the exact
     // layout that we sent back to WM.
-    private SplitDisplayLayout mRotateSplitLayout;
+    private LegacySplitDisplayLayout mRotateSplitLayout;
 
     private boolean mIsKeyguardShowing;
     private boolean mVisible = false;
@@ -109,7 +109,7 @@
     private boolean mAdjustedForIme = false;
     private boolean mHomeStackResizable = false;
 
-    public SplitScreenController(Context context,
+    public LegacySplitScreenController(Context context,
             DisplayController displayController, SystemWindows systemWindows,
             DisplayImeController imeController, Handler handler, TransactionPool transactionPool,
             ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
@@ -123,7 +123,7 @@
         mTransactionPool = transactionPool;
         mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
         mTaskOrganizer = shellTaskOrganizer;
-        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
+        mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
         mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
                 shellTaskOrganizer);
         mRotationController =
@@ -134,8 +134,8 @@
                     WindowContainerTransaction t = new WindowContainerTransaction();
                     DisplayLayout displayLayout =
                             new DisplayLayout(mDisplayController.getDisplayLayout(display));
-                    SplitDisplayLayout sdl =
-                            new SplitDisplayLayout(mContext, displayLayout, mSplits);
+                    LegacySplitDisplayLayout sdl =
+                            new LegacySplitDisplayLayout(mContext, displayLayout, mSplits);
                     sdl.rotateTo(toRotation);
                     mRotateSplitLayout = sdl;
                     final int position = isDividerVisible()
@@ -229,7 +229,7 @@
         if (displayId != DEFAULT_DISPLAY) {
             return;
         }
-        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+        mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
                 mDisplayController.getDisplayLayout(displayId), mSplits);
         mImeController.addPositionProcessor(mImePositionProcessor);
         mDisplayController.addDisplayChangingController(mRotationController);
@@ -251,7 +251,7 @@
         if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
             return;
         }
-        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+        mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
                 mDisplayController.getDisplayLayout(displayId), mSplits);
         if (mRotateSplitLayout == null) {
             int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
@@ -586,7 +586,7 @@
         }
     }
 
-    SplitDisplayLayout getSplitLayout() {
+    LegacySplitDisplayLayout getSplitLayout() {
         return mSplitLayout;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
index af451ae..02c82de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -43,9 +43,9 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
-class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
-    private static final String TAG = "SplitScreenTaskListener";
-    private static final boolean DEBUG = SplitScreenController.DEBUG;
+class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
+    private static final String TAG = LegacySplitScreenTaskListener.class.getSimpleName();
+    private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
 
     private final ShellTaskOrganizer mTaskOrganizer;
     private final SyncTransactionQueue mSyncQueue;
@@ -58,12 +58,12 @@
     SurfaceControl mPrimaryDim;
     SurfaceControl mSecondaryDim;
     Rect mHomeBounds = new Rect();
-    final SplitScreenController mSplitScreenController;
+    final LegacySplitScreenController mSplitScreenController;
     private boolean mSplitScreenSupported = false;
 
     final SurfaceSession mSurfaceSession = new SurfaceSession();
 
-    SplitScreenTaskListener(SplitScreenController splitScreenController,
+    LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController,
                     ShellTaskOrganizer shellTaskOrganizer,
                     SyncTransactionQueue syncQueue) {
         mSplitScreenController = splitScreenController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
index 06f4ef1..1e9223c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import android.annotation.Nullable;
 import android.content.Context;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index 0307206..68da35d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -88,8 +88,8 @@
         mTaskOrganizer = taskOrganizer;
     }
 
-    void dismissOrMaximizeDocked(final SplitScreenTaskListener tiles, SplitDisplayLayout layout,
-            final boolean dismissOrMaximize) {
+    void dismissOrMaximizeDocked(final LegacySplitScreenTaskListener tiles,
+            LegacySplitDisplayLayout layout, final boolean dismissOrMaximize) {
         mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
     }
 
@@ -114,7 +114,7 @@
         mExecutor.execute(mSetTouchableRegionRunnable);
     }
 
-    void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
+    void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) {
         WindowContainerTransaction t = new WindowContainerTransaction();
         splitLayout.resizeSplits(position, t);
         new WindowOrganizer().applyTransaction(t);
@@ -141,7 +141,7 @@
      * split is minimized. This actually "sticks out" of the secondary split area, but when in
      * minimized mode, the secondary split gets a 'negative' crop to expose it.
      */
-    boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent,
+    boolean applyHomeTasksMinimized(LegacySplitDisplayLayout layout, WindowContainerToken parent,
             @NonNull WindowContainerTransaction wct) {
         // Resize the home/recents stacks to the larger minimized-state size
         final Rect homeBounds;
@@ -189,7 +189,7 @@
      *
      * @return whether the home stack is resizable
      */
-    boolean applyEnterSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout) {
+    boolean applyEnterSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout) {
         // Set launchtile first so that any stack created after
         // getAllRootTaskInfos and before reparent (even if unlikely) are placed
         // correctly.
@@ -241,7 +241,7 @@
      *                          split (thus resulting in the top of the secondary split becoming
      *                          fullscreen. {@code false} resolves the other way.
      */
-    void applyDismissSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout,
+    void applyDismissSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout,
             boolean dismissOrMaximize) {
         // Set launch root first so that any task created after getChildContainers and
         // before reparent (pretty unlikely) are put into fullscreen.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index e8c6cb7..d5db0cc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -45,6 +45,7 @@
 import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
 
 import java.io.PrintWriter;
+import java.util.concurrent.Executor;
 
 /**
  * Manages and manipulates the one handed states, transitions, and gesture for phones.
@@ -169,7 +170,7 @@
     @Nullable
     public static OneHandedController create(
             Context context, DisplayController displayController,
-            TaskStackListenerImpl taskStackListener) {
+            TaskStackListenerImpl taskStackListener, Executor executor) {
         if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
             Slog.w(TAG, "Device doesn't support OneHanded feature");
             return null;
@@ -182,7 +183,7 @@
         OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
                 context, displayController);
         OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
-                context, displayController, animationController, tutorialHandler);
+                context, displayController, animationController, tutorialHandler, executor);
         IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                 ServiceManager.getService(Context.OVERLAY_SERVICE));
         return new OneHandedController(context, displayController, organizer, touchHandler,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 0311030..7fb1faa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -47,6 +47,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 
 /**
  * Manages OneHanded display areas such as offset.
@@ -151,7 +152,8 @@
     public OneHandedDisplayAreaOrganizer(Context context,
             DisplayController displayController,
             OneHandedAnimationController animationController,
-            OneHandedTutorialHandler tutorialHandler) {
+            OneHandedTutorialHandler tutorialHandler, Executor executor) {
+        super(executor);
         mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback);
         mAnimationController = animationController;
         mDisplayController = displayController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 9081783..4b283e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -66,7 +66,7 @@
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.pip.phone.PipMotionHelper;
 import com.android.wm.shell.pip.phone.PipUpdateThread;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -142,7 +142,7 @@
     private final int mEnterExitAnimationDuration;
     private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
     private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     protected final ShellTaskOrganizer mTaskOrganizer;
 
     // These callbacks are called on the update thread
@@ -265,7 +265,7 @@
             @NonNull PipBoundsAlgorithm boundsHandler,
             @NonNull PipMenuController pipMenuController,
             @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             @NonNull DisplayController displayController,
             @NonNull PipUiEventLogger pipUiEventLogger,
             @NonNull ShellTaskOrganizer shellTaskOrganizer) {
@@ -1118,7 +1118,7 @@
     }
 
     /**
-     * Sync with {@link SplitScreen} on destination bounds if PiP is going to split screen.
+     * Sync with {@link LegacySplitScreen} on destination bounds if PiP is going to split screen.
      *
      * @param destinationBoundsOut contain the updated destination bounds if applicable
      * @return {@code true} if destinationBounds is altered for split screen
@@ -1128,15 +1128,15 @@
             return false;
         }
 
-        SplitScreen splitScreen = mSplitScreenOptional.get();
-        if (!splitScreen.isDividerVisible()) {
+        LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get();
+        if (!legacySplitScreen.isDividerVisible()) {
             // fail early if system is not in split screen mode
             return false;
         }
 
         // PiP window will go to split-secondary mode instead of fullscreen, populates the
         // split screen bounds here.
-        destinationBoundsOut.set(splitScreen.getDividerView()
+        destinationBoundsOut.set(legacySplitScreen.getDividerView()
                 .getNonMinimizedSplitScreenSecondaryBounds());
         return true;
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
index 3486761..02f6f8c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
@@ -52,7 +52,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterSplitScreenTest(
+class EnterLegacySplitScreenTest(
     rotationName: String,
     rotation: Int
 ) : SplitScreenTestBase(rotationName, rotation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
similarity index 97%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
index 7c47d1f..33306bf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.platform.test.annotations.Presubmit
 import android.util.Rational
@@ -45,7 +45,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitSplitScreenTest(
+class ExitLegacySplitScreenTest(
     rotationName: String,
     rotation: Int
 ) : SplitScreenTestBase(rotationName, rotation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
index 00979fa..cc02aa3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
@@ -54,7 +54,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SplitScreenToLauncherTest(
+class LegacySplitScreenToLauncherTest(
     testName: String,
     flickerSpec: Flicker
 ) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
similarity index 97%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
index c85561d..bb80726 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
@@ -54,7 +54,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppToSplitScreenTest(
+class OpenAppToLegacySplitScreenTest(
     testName: String,
     flickerSpec: Flicker
 ) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
index 7c83846..e3beb41 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.graphics.Region
 import android.util.Rational
@@ -63,7 +63,7 @@
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 159096424)
-class ResizeSplitScreenTest(
+class ResizeLegacySplitScreenTest(
     testName: String,
     flickerSpec: Flicker
 ) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
index be8f9bc..ae2200c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateOneLaunchedAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
index 2e05c2a..a1b44f0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/RotateTwoLaunchedAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
index 42c509d..a2e325e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
 
 import com.android.wm.shell.flicker.NonRotationTestBase
 import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
similarity index 99%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index f79b21f..81cdbf0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -47,7 +47,7 @@
 @RunWith(Parameterized::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @FlakyTest(bugId = 161435597)
-class PipSplitScreenTest(
+class PipLegacySplitScreenTest(
     rotationName: String,
     rotation: Int
 ) : AppTestBase(rotationName, rotation) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 9fdd59b..708a6c5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -58,7 +58,7 @@
                 mContext,
                 getConfiguration(false),
                 mLayoutChangeListener,
-                mRootLeash);
+                b -> b.setParent(mRootLeash));
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index aa0eb2f..c170563 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -49,7 +49,8 @@
         MockitoAnnotations.initMocks(this);
         final Configuration configuration = new Configuration();
         configuration.setToDefaults();
-        mSplitWindowManager = new SplitWindowManager(mContext, configuration, mSurfaceControl);
+        mSplitWindowManager = new SplitWindowManager(mContext, configuration,
+                b -> b.setParent(mSurfaceControl));
         when(mSplitLayout.getDividerBounds()).thenReturn(
                 new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
                         configuration.windowConfiguration.getBounds().height()));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index 92d4bee..912418d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -61,8 +61,8 @@
 
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target;
-import com.android.wm.shell.splitscreen.DividerView;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.DividerView;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -90,7 +90,7 @@
     private ActivityTaskManager mActivityTaskManager;
 
     @Mock
-    private SplitScreen mSplitScreen;
+    private LegacySplitScreen mLegacySplitScreen;
 
     @Mock
     private DragAndDropPolicy.Starter mStarter;
@@ -123,7 +123,7 @@
         mInsets = Insets.of(0, 0, 0, 0);
 
         DividerView divider = mock(DividerView.class);
-        doReturn(divider).when(mSplitScreen).getDividerView();
+        doReturn(divider).when(mLegacySplitScreen).getDividerView();
         doReturn(new Rect(50, 0, 100, 100)).when(divider)
                 .getNonMinimizedSplitScreenSecondaryBounds();
 
@@ -131,9 +131,10 @@
             Consumer<Boolean> callback = invocation.getArgument(0);
             callback.accept(true);
             return null;
-        }).when(mSplitScreen).registerInSplitScreenListener(any());
+        }).when(mLegacySplitScreen).registerInSplitScreenListener(any());
 
-        mPolicy = new DragAndDropPolicy(mContext, mActivityTaskManager, mSplitScreen, mStarter);
+        mPolicy = new DragAndDropPolicy(
+                mContext, mActivityTaskManager, mLegacySplitScreen, mStarter);
         mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
         mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
         setClipDataResizeable(mNonResizeableActivityClipData, false);
@@ -207,7 +208,7 @@
     }
 
     private void setInSplitScreen(boolean inSplitscreen) {
-        doReturn(inSplitscreen).when(mSplitScreen).isDividerVisible();
+        doReturn(inSplitscreen).when(mLegacySplitScreen).isDividerVisible();
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
index 2e4fd6a..e0c835b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
@@ -93,7 +93,7 @@
         when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
 
         HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer(
-                mContext, mMockDisplayController);
+                mContext, mMockDisplayController, Runnable::run);
         mOrganizer = Mockito.spy(organizer);
         doNothing().when(mOrganizer).unregisterOrganizer();
         doNothing().when(mOrganizer).applyBoundsAndOffsets(any(), any(), any(), any());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 8ef077e..e37e154 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -93,7 +93,8 @@
         final OneHandedAnimationController animationController = new OneHandedAnimationController(
                 mContext);
         OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
-                mContext, mMockDisplayController, animationController, mMockTutorialHandler);
+                mContext, mMockDisplayController, animationController, mMockTutorialHandler,
+                Runnable::run);
 
         assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index 6d1a3c4..5d742b3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -111,7 +111,8 @@
         mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext,
                 mMockDisplayController,
                 mMockAnimationController,
-                mTutorialHandler);
+                mTutorialHandler,
+                Runnable::run);
         mSpyUpdateHandler = spy(new Handler(OneHandedThread.get().getLooper(), mUpdateCallback));
         mDisplayAreaOrganizer.setUpdateHandler(mSpyUpdateHandler);
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 45e4241..b5d10d7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -45,7 +45,7 @@
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.pip.phone.PhonePipMenuController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -69,7 +69,7 @@
     @Mock private PhonePipMenuController mMockPhonePipMenuController;
     @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
     @Mock private PipUiEventLogger mMockPipUiEventLogger;
-    @Mock private Optional<SplitScreen> mMockOptionalSplitScreen;
+    @Mock private Optional<LegacySplitScreen> mMockOptionalSplitScreen;
     @Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
     private PipBoundsState mPipBoundsState;
 
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 4b4aa92..6f4ba89 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -696,7 +696,7 @@
     { "nSetRevealClip",        "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
 
     { "nSetAlpha",             "(JF)Z",  (void*) android_view_RenderNode_setAlpha },
-    { "nSetRenderEffect",      "(JJ)V",  (void*) android_view_RenderNode_setRenderEffect },
+    { "nSetRenderEffect",      "(JJ)Z",  (void*) android_view_RenderNode_setRenderEffect },
     { "nSetHasOverlappingRendering", "(JZ)Z",
             (void*) android_view_RenderNode_setHasOverlappingRendering },
     { "nSetUsageHint",    "(JI)V", (void*) android_view_RenderNode_setUsageHint },
diff --git a/lowpan/java/android/net/lowpan/LowpanManager.java b/lowpan/java/android/net/lowpan/LowpanManager.java
index 76876ce..33b35e6 100644
--- a/lowpan/java/android/net/lowpan/LowpanManager.java
+++ b/lowpan/java/android/net/lowpan/LowpanManager.java
@@ -24,6 +24,10 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.Map;
@@ -97,10 +101,14 @@
      *
      * @param context the application context
      * @param service the Binder interface
-     * @param looper the default Looper to run callbacks on
      * @hide - hide this because it takes in a parameter of type ILowpanManager, which is a system
      *     private class.
      */
+    public LowpanManager(Context context, ILowpanManager service) {
+        this(context, service, BackgroundThread.get().getLooper());
+    }
+
+    @VisibleForTesting
     public LowpanManager(Context context, ILowpanManager service, Looper looper) {
         mContext = context;
         mService = service;
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index 700e7be..b64ba88 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -117,9 +117,9 @@
      * <p>A descrambler instance can have only one key slot to link, but a key slot can hold a few
      * keys for different purposes. {@link Tuner.VOID_KEYTOKEN} is considered valid.
      *
-     * @param keyToken the token to be used to link the key slot. Use {@link Tuner.VOID_KEYTOKEN}
+     * @param keyToken the token to be used to link the key slot. Use {@link Tuner#VOID_KEYTOKEN}
      *        to remove the current key from descrambler. If the current keyToken comes from a
-     *        MediaCas session, use {@link Tuner.VOID_KEYTOKEN} to remove current key before
+     *        MediaCas session, use {@link Tuner#VOID_KEYTOKEN} to remove current key before
      *        closing the MediaCas session.
      * @return result status of the operation.
      */
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 20f02a4..dec0709 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -555,7 +555,6 @@
      */
     private native Frontend nativeOpenFrontendByHandle(int handle);
     @Result
-    private native int nativeCloseFrontendByHandle(int handle);
     private native int nativeTune(int type, FrontendSettings settings);
     private native int nativeStopTune();
     private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
@@ -686,7 +685,7 @@
      *
      * <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
      * to get frontend resource. If the client can't get the resource, this call returns {@link
-     * Result#RESULT_UNAVAILABLE}.
+     * #RESULT_UNAVAILABLE}.
      *
      * <p>
      * This locks the frontend to a frequency by providing signal
@@ -700,7 +699,7 @@
      *
      * <p>Tuning with {@link android.media.tv.tuner.frontend.DtmbFrontendSettings} is only
      * supported in Tuner 1.1 or higher version. Unsupported version will cause no-op. Use {@link
-     * TunerVersionChecker.getTunerVersion()} to get the version information.
+     * TunerVersionChecker#getTunerVersion()} to get the version information.
      *
      * @param settings Signal delivery information the frontend uses to
      *                 search and lock the signal.
@@ -749,7 +748,7 @@
      *
      * <p>Scanning with {@link android.media.tv.tuner.frontend.DtmbFrontendSettings} is only
      * supported in Tuner 1.1 or higher version. Unsupported version will cause no-op. Use {@link
-     * TunerVersionChecker.getTunerVersion()} to get the version information.
+     * TunerVersionChecker#getTunerVersion()} to get the version information.
      *
      * @param settings A {@link FrontendSettings} to configure the frontend.
      * @param scanType The scan type.
@@ -855,7 +854,7 @@
      * <p>This retrieve the statuses of the frontend for given status types.
      *
      * @param statusTypes an array of status types which the caller requests. Any types that are not
-     *        in {@link FrontendInfo.getStatusCapabilities()} would be ignored.
+     *        in {@link FrontendInfo#getStatusCapabilities()} would be ignored.
      * @return statuses which response the caller's requests. {@code null} if the operation failed.
      */
     @Nullable
@@ -904,7 +903,7 @@
      * use the output from CI-CAM as the input after this call.
      *
      * <p> Note that this API is used to connect the CI-CAM to the Demux module while
-     * {@link connectFrontendToCiCam(int)} is used to connect CI-CAM to the Frontend module.
+     * {@link #connectFrontendToCiCam(int)} is used to connect CI-CAM to the Frontend module.
      *
      * @param ciCamId specify CI-CAM Id to connect.
      * @return result status of the operation.
@@ -926,20 +925,20 @@
      * the TS directly from the frontend.
      *
      * <p> Note that this API is used to connect the CI-CAM to the Frontend module while
-     * {@link connectCiCam(int)} is used to connect CI-CAM to the Demux module.
+     * {@link #connectCiCam(int)} is used to connect CI-CAM to the Demux module.
      *
      * <p>Use {@link #disconnectFrontendToCiCam(int)} to disconnect.
      *
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-     * no-op and return {@link INVALID_LTS_ID}. Use {@link TunerVersionChecker.getTunerVersion()} to
-     * check the version.
+     * no-op and return {@link #INVALID_LTS_ID}. Use {@link TunerVersionChecker#getTunerVersion()}
+     * to check the version.
      *
      * @param ciCamId specify CI-CAM Id, which is the id of the Conditional Access Modules (CAM)
      *                Common Interface (CI), to link.
      * @return Local transport stream id when connection is successfully established. Failed
-     *         operation returns {@link INVALID_LTS_ID} while unsupported version also returns
-     *         {@link INVALID_LTS_ID}. Check the current HAL version using
-     *         {@link TunerVersionChecker.getTunerVersion()}.
+     *         operation returns {@link #INVALID_LTS_ID} while unsupported version also returns
+     *         {@link #INVALID_LTS_ID}. Check the current HAL version using
+     *         {@link TunerVersionChecker#getTunerVersion()}.
      */
     public int connectFrontendToCiCam(int ciCamId) {
         if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
@@ -957,7 +956,7 @@
      * <p>The demux will use the output from the frontend as the input after this call.
      *
      * <p> Note that this API is used to disconnect the CI-CAM to the Demux module while
-     * {@link disconnectFrontendToCiCam(int)} is used to disconnect CI-CAM to the Frontend module.
+     * {@link #disconnectFrontendToCiCam(int)} is used to disconnect CI-CAM to the Frontend module.
      *
      * @return result status of the operation.
      */
@@ -975,15 +974,15 @@
      * <p>It is used by the client to unlink CI-CAM to a Frontend.
      *
      * <p> Note that this API is used to disconnect the CI-CAM to the Demux module while
-     * {@link disconnectCiCam(int)} is used to disconnect CI-CAM to the Frontend module.
+     * {@link #disconnectCiCam(int)} is used to disconnect CI-CAM to the Frontend module.
      *
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
      *
      * @param ciCamId specify CI-CAM Id, which is the id of the Conditional Access Modules (CAM)
      *                Common Interface (CI), to disconnect.
      * @return result status of the operation. Unsupported version would return
-     *         {@link RESULT_UNAVAILABLE}
+     *         {@link #RESULT_UNAVAILABLE}
      */
     @Result
     public int disconnectFrontendToCiCam(int ciCamId) {
@@ -1292,7 +1291,7 @@
     /**
      * Opens a Descrambler in tuner.
      *
-     * @return  a {@link Descrambler} object.
+     * @return a {@link Descrambler} object.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER)
     @Nullable
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index e482875..25457a7 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -251,9 +251,9 @@
          * Sets the Audio Stream Type.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
-         * @param audioStreamType the {@link AudioStreamType} to set.
+         * @param audioStreamType the audio stream type to set.
          */
         @NonNull
         public Builder setAudioStreamType(@AudioStreamType int audioStreamType) {
@@ -269,9 +269,9 @@
          * Sets the Video Stream Type.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
-         * @param videoStreamType the {@link VideoStreamType} to set.
+         * @param videoStreamType the video stream type to set.
          */
         @NonNull
         public Builder setVideoStreamType(@VideoStreamType int videoStreamType) {
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 451f54c..96371e5 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -323,25 +323,25 @@
     }
 
     /**
-     * Configure the Filter to monitor scrambling status and ip cid change. Set corresponding bit of
-     * {@link MonitorEventTypeMask} to monitor the change. Reset to stop monitoring.
+     * Configure the Filter to monitor scrambling status and ip cid change. Set corresponding bit
+     * to monitor the change. Reset to stop monitoring.
      *
      * <p>{@link ScramblingStatusEvent} should be sent at the following two scenarios:
      * <ul>
-     *   <li>When this method is called with {@link MONITOR_EVENT_SCRAMBLING_STATUS}, the first
+     *   <li>When this method is called with {@link #MONITOR_EVENT_SCRAMBLING_STATUS}, the first
      *       detected scrambling status should be sent.
      *   <li>When the Scrambling status transits into different status, event should be sent.
      *     <ul/>
      *
      * <p>{@link IpCidChangeEvent} should be sent at the following two scenarios:
      * <ul>
-     *   <li>When this method is called with {@link MONITOR_EVENT_IP_CID_CHANGE}, the first detected
-     *       CID for the IP should be sent.
+     *   <li>When this method is called with {@link #MONITOR_EVENT_IP_CID_CHANGE}, the first
+     *       detected CID for the IP should be sent.
      *   <li>When the CID is changed to different value for the IP filter, event should be sent.
      *     <ul/>
      *
      * <p>This configuration is only supported in Tuner 1.1 or higher version. Unsupported version
-     * will cause no-op. Use {@link TunerVersionChecker.getTunerVersion()} to get the version
+     * will cause no-op. Use {@link TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      *
      * @param monitorEventTypesMask Types of event to be monitored. Set corresponding bit to
diff --git a/media/java/android/media/tv/tuner/filter/IpCidChangeEvent.java b/media/java/android/media/tv/tuner/filter/IpCidChangeEvent.java
index c0043f3..2894c02 100644
--- a/media/java/android/media/tv/tuner/filter/IpCidChangeEvent.java
+++ b/media/java/android/media/tv/tuner/filter/IpCidChangeEvent.java
@@ -22,7 +22,7 @@
  * Ip Cid Change event sent from {@link Filter} objects new ip cid.
  *
  * <p>This event is only sent in Tuner 1.1 or higher version. Use
- * {@link TunerVersionChecker.getTunerVersion()} to get the version information.
+ * {@link TunerVersionChecker#getTunerVersion()} to get the version information.
  *
  * @hide
  */
@@ -38,7 +38,7 @@
      * Gets ip cid.
      *
      * <p>This event is only sent in Tuner 1.1 or higher version. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to get the version information.
+     * {@link TunerVersionChecker#getTunerVersion()} to get the version information.
      */
     public int getIpCid() {
         return mCid;
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 62d55f5..4b69807 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -100,7 +100,7 @@
      * Gets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}.
      *
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would return
-     * default value. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * default value. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @IntRange(from = 0, to = 0xefff)
     public int getIpFilterContextId() {
@@ -194,7 +194,7 @@
          * Sets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          */
         @NonNull
         public Builder setIpFilterContextId(int ipContextId) {
diff --git a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
index 1bbd6e3..6a41c74 100644
--- a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
@@ -65,8 +65,8 @@
      * Get the MPU sequence number of the filtered data.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link android.media.tv.tuner.Tuner.INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version
+     * return {@link android.media.tv.tuner.Tuner#INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
     public int getMpuSequenceNumber() {
@@ -78,8 +78,8 @@
      * and has the same format as the PTS in ISO/IEC 13818-1.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link android.media.tv.tuner.Tuner.INVALID_TIMESTAMP}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version
+     * return {@link android.media.tv.tuner.Tuner#INVALID_TIMESTAMP}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
     public long getPts() {
@@ -90,8 +90,8 @@
      * Get the address of the first macroblock in the slice defined in ITU-T Rec. H.264.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link android.media.tv.tuner.Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version
+     * return {@link android.media.tv.tuner.Tuner#INVALID_FIRST_MACROBLOCK_IN_SLICE}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
     public int getFirstMacroblockInSlice() {
@@ -102,8 +102,8 @@
      * Get the offset of the recorded keyframe from MMT Packet Table.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link RecordSettings.TS_INDEX_INVALID}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the
+     * return {@link RecordSettings#TS_INDEX_INVALID}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the
      * version information.
      */
     @RecordSettings.TsIndexMask
diff --git a/media/java/android/media/tv/tuner/filter/RestartEvent.java b/media/java/android/media/tv/tuner/filter/RestartEvent.java
index 45ab7d9..0696301 100644
--- a/media/java/android/media/tv/tuner/filter/RestartEvent.java
+++ b/media/java/android/media/tv/tuner/filter/RestartEvent.java
@@ -22,7 +22,7 @@
  * An Event that the client would reveice after stopping, reconfiguring and restarting a filter.
  *
  * <p>After stopping and restarting the filter, the client has to discard all coming events until
- * it receive {@link RestartedEvent} to avoid using the events from the previous configuration.
+ * it receives {@link RestartEvent} to avoid using the events from the previous configuration.
  *
  * <p>Recofiguring must happen after stopping the filter.
  *
diff --git a/media/java/android/media/tv/tuner/filter/ScramblingStatusEvent.java b/media/java/android/media/tv/tuner/filter/ScramblingStatusEvent.java
index fef5396..103d024 100644
--- a/media/java/android/media/tv/tuner/filter/ScramblingStatusEvent.java
+++ b/media/java/android/media/tv/tuner/filter/ScramblingStatusEvent.java
@@ -22,7 +22,7 @@
  * Scrambling Status event sent from {@link Filter} objects with Scrambling Status type.
  *
  * <p>This event is only sent in Tuner 1.1 or higher version. Use
- * {@link TunerVersionChecker.getTunerVersion()} to get the version information.
+ * {@link TunerVersionChecker#getTunerVersion()} to get the version information.
  *
  * @hide
  */
@@ -38,7 +38,7 @@
      * Gets Scrambling Status Type.
      *
      * <p>This event field is only sent in Tuner 1.1 or higher version. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to get the version information.
+     * {@link TunerVersionChecker#getTunerVersion()} to get the version information.
      */
     @Filter.ScramblingStatus
     public int getScramblingStatus() {
diff --git a/media/java/android/media/tv/tuner/filter/TsRecordEvent.java b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java
index 2816199..bf2c000 100644
--- a/media/java/android/media/tv/tuner/filter/TsRecordEvent.java
+++ b/media/java/android/media/tv/tuner/filter/TsRecordEvent.java
@@ -83,8 +83,8 @@
      * and has the same format as the PTS in ISO/IEC 13818-1.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link android.media.tv.tuner.Tuner.INVALID_TIMESTAMP}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version
+     * return {@link android.media.tv.tuner.Tuner#INVALID_TIMESTAMP}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
     public long getPts() {
@@ -95,8 +95,8 @@
      * Get the address of the first macroblock in the slice defined in ITU-T Rec. H.264.
      *
      * <p>This field is only supported in Tuner 1.1 or higher version. Unsupported version will
-     * return {@link android.media.tv.tuner.Tuner.INVALID_FIRST_MACROBLOCK_IN_SLICE}. Use
-     * {@link android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version
+     * return {@link android.media.tv.tuner.Tuner#INVALID_FIRST_MACROBLOCK_IN_SLICE}. Use
+     * {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
      * information.
      */
     public int getFirstMacroblockInSlice() {
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index c6a5bb0..b2c3fd2 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -264,7 +264,7 @@
          * Set Aft flag.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
          * @param aftFlag the value to set the aft flag. The default value is
          * {@link #AFT_FLAG_UNDEFINED}.
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
index dd386b0..e856779 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
@@ -46,8 +46,7 @@
     /**
      * Gets modulation capability.
      *
-     * @return full modulation capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.Modulation} is true, then that modulation is supported.
+     * @return the bit mask of all the supported modulations.
      */
     @DtmbFrontendSettings.Modulation
     public int getModulationCapability() {
@@ -57,9 +56,7 @@
     /**
      * Gets Transmission Mode capability.
      *
-     * @return full Transmission Mode capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.TransmissionMode} is true, then that transmission mode
-     * is supported.
+     * @return the bit mask of all the supported transmission modes.
      */
     @DtmbFrontendSettings.TransmissionMode
     public int getTransmissionModeCapability() {
@@ -69,9 +66,7 @@
     /**
      * Gets Guard Interval capability.
      *
-     * @return full Guard Interval capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.GuardInterval} is true, then that Guard Interval is
-     * supported.
+     * @return the bit mask of all the supported guard intervals.
      */
     @DtmbFrontendSettings.GuardInterval
     public int getGuardIntervalCapability() {
@@ -81,9 +76,7 @@
     /**
      * Gets Time Interleave Mode capability.
      *
-     * @return full Time Interleave Mode capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.TimeInterleaveMode} is true, then that Time Interleave
-     * Mode is supported.
+     * @return the bit mask of all the supported time interleave modes.
      */
     @DtmbFrontendSettings.TimeInterleaveMode
     public int getTimeInterleaveModeCapability() {
@@ -93,8 +86,7 @@
     /**
      * Gets Code Rate capability.
      *
-     * @return full Code Rate capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.CodeRate} is true, then that Code Rate is supported.
+     * @return the bit mask of all the supported code rates.
      */
     @DtmbFrontendSettings.CodeRate
     public int getCodeRateCapability() {
@@ -104,8 +96,7 @@
     /**
      * Gets Bandwidth capability.
      *
-     * @return full Bandwidth capabilies. If the caps bitwise AND with any value from
-     * bit masks {@link DtmbFrontendSettings.Bandwidth} is true, then that Bandwidth is supported.
+     * @return the bit mask of all the supported bandwidth.
      */
     @DtmbFrontendSettings.Bandwidth
     public int getBandwidthCapability() {
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index d85e60d..c1d0833 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -29,7 +29,7 @@
  * Frontend settings for DTMB.
  *
  * <p>DTMB Frontend is only supported in Tuner HAL 1.1 or higher. Use {@link
- * android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version information.
+ * android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version information.
  *
  * @hide
  */
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
index 948f4a7..0e08c15 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendCapabilities.java
@@ -45,9 +45,9 @@
     /**
      * Gets inner FEC capability.
      *
-     * @deprecated Use {@link getInnerFecCapability()} with long return value instead. This function
-     *             returns the correct cap value when the value is not bigger than the max integer
-     *             value. Otherwise it returns {@link FrontendSettings#FEC_UNDEFINED}.
+     * @deprecated Use {@link #getInnerFecCapability()} with long return value instead. This
+     *             function returns the correct cap value when the value is not bigger than the max
+     *             integer value. Otherwise it returns {@link FrontendSettings#FEC_UNDEFINED}.
      */
     @Deprecated
     @FrontendSettings.InnerFec
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index a611da6..db28631 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -120,7 +120,7 @@
 
 
     /**
-     * @deprecated Use the {@link FrontendSettings#FrontendSpectralInversion} instead.
+     * @deprecated Use the {@code FrontendSpectralInversion} instead.
      * @hide
      */
     @Deprecated
@@ -439,7 +439,7 @@
          * Set the time interleave mode.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
          * @param interleaveMode the value to set as the time interleave mode. Default value is
          * {@link #TIME_INTERLEAVE_MODE_UNDEFINED}.
@@ -456,7 +456,7 @@
          * Set the Bandwidth.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
          * @param bandwidth the value to set as the bandwidth. Default value is
          * {@link #BANDWIDTH_UNDEFINED}.
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index a2a602a..f68d554 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -344,7 +344,7 @@
      * Get if the client can handle the Diseqc Rx Message or not. Default value is false.
      *
      * The setter {@link Builder#setCanHandleDiseqcRxMessage(boolean)} is only supported with
-     * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker.getTunerVersion()} to check the
+     * Tuner HAL 1.1 or higher. Use {@link TunerVersionChecker#getTunerVersion()} to check the
      * version.
      */
     public boolean canHandleDiseqcRxMessage() {
@@ -394,7 +394,7 @@
          * Set the scan type.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
          * @param scanType the value to set as the scan type. Default value is
          * {@link android.media.tv.tuner.frontend.DvbsFrontendSettings#DVBS_SCAN_TYPE_UNDEFINED}.
@@ -414,7 +414,7 @@
          * channel in the hardware layer.
          *
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-         * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          */
         @NonNull
         public Builder setCanHandleDiseqcRxMessage(boolean canHandleDiseqcMessage) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 07d1797..536c7b8 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -586,7 +586,7 @@
          *
          * <p>{@link #TRANSMISSION_MODE_EXTENDED_8K}, {@link #TRANSMISSION_MODE_EXTENDED_16K} and
          * {@link #TRANSMISSION_MODE_EXTENDED_32K} are only supported by Tuner HAL 1.1 or higher.
-         * Unsupported version would cause no-op. Use {@link TunerVersionChecker.getTunerVersion()}
+         * Unsupported version would cause no-op. Use {@link TunerVersionChecker#getTunerVersion()}
          * to check the version.
          *
          * <p>Default value is {@link #TRANSMISSION_MODE_UNDEFINED}.
@@ -617,7 +617,7 @@
          * <p>{@link #CONSTELLATION_QPSK_R}, {@link #CONSTELLATION_16QAM_R},
          * {@link #CONSTELLATION_64QAM_R} and {@link #CONSTELLATION_256QAM_Rare} are only supported
          * by Tuner HAL 1.1 or higher. Unsupported version would cause no-op. Use
-         * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+         * {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
          * <p>Default value is {@link #CONSTELLATION_UNDEFINED}.
          */
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
index f3e9476..67d6e9d 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendInfo.java
@@ -57,7 +57,7 @@
     /**
      * Gets frontend ID.
      *
-     * @return the frontend ID or {@link android.media.tv.tuner.Tuner.INVALID_FRONTEND_ID}
+     * @return the frontend ID or {@link android.media.tv.tuner.Tuner#INVALID_FRONTEND_ID}
      *         if invalid
      */
     public int getId() {
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
index f8470b11..4bfe807 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java
@@ -321,7 +321,7 @@
      * Set Spectral Inversion.
      *
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
      *
      * @param inversion the value to set as the spectral inversion. Default value is {@link
      * #FRONTEND_SPECTRAL_INVERSION_UNDEFINED}.
@@ -338,7 +338,7 @@
      * would be no-op.
      *
      * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
-     * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
      *
      * @param endFrequency the end frequency used during blind scan. The default value is
      * {@link android.media.tv.tuner.Tuner#INVALID_FRONTEND_SETTING_FREQUENCY}.
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index c762da6..4acaa58 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -680,7 +680,7 @@
      * Gets an array of the current extended bit error ratio.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     public int[] getBers() {
@@ -696,7 +696,7 @@
      * Gets an array of the current code rates.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     @FrontendSettings.InnerFec
@@ -713,7 +713,7 @@
      * Gets the current bandwidth information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @FrontendBandwidth
     public int getBandwidth() {
@@ -729,7 +729,7 @@
      * Gets the current guard interval information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @FrontendGuardInterval
     public int getGuardInterval() {
@@ -745,7 +745,7 @@
      * Gets the current transmission mode information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @FrontendTransmissionMode
     public int getTransmissionMode() {
@@ -762,7 +762,7 @@
      * since the last tune operation.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     public int getUec() {
         TunerVersionChecker.checkHigherOrEqualVersionTo(
@@ -777,7 +777,7 @@
      * Gets the current DVB-T2 system id.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @IntRange(from = 0, to = 0xffff)
     public int getSystemId() {
@@ -793,7 +793,7 @@
      * Gets an array of the current interleaving mode information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     @FrontendInterleaveMode
@@ -811,7 +811,7 @@
      * channels.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     @IntRange(from = 0, to = 0xff)
@@ -828,7 +828,7 @@
      * Gets an array of the Transport Stream Data Rate in BPS of the current channel.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     public int[] getTsDataRate() {
@@ -844,7 +844,7 @@
      * Gets an array of the current extended modulations information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @NonNull
     @FrontendModulation
@@ -861,7 +861,7 @@
      * Gets the current roll off information.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     @FrontendRollOff
     public int getRollOff() {
@@ -877,7 +877,7 @@
      * Gets is MISO enabled or not.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     public boolean isMisoEnabled() {
         TunerVersionChecker.checkHigherOrEqualVersionTo(
@@ -892,7 +892,7 @@
      * Gets is the Code Rate of the frontend is linear or not.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     public boolean isLinear() {
         TunerVersionChecker.checkHigherOrEqualVersionTo(
@@ -907,7 +907,7 @@
      * Gets is the Short Frames enabled or not.
      *
      * <p>This query is only supported by Tuner HAL 1.1 or higher. Use
-     * {@link TunerVersionChecker.getTunerVersion()} to check the version.
+     * {@link TunerVersionChecker#getTunerVersion()} to check the version.
      */
     public boolean isShortFramesEnabled() {
         TunerVersionChecker.checkHigherOrEqualVersionTo(
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index c7fb50f..79f6cbf 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -139,12 +139,17 @@
     name: "libmedia_tv_tuner",
     srcs: [
         "android_media_tv_Tuner.cpp",
+        "tuner/DemuxClient.cpp",
+        "tuner/FilterClient.cpp",
+        "tuner/FrontendClient.cpp",
+        "tuner/TunerClient.cpp",
     ],
 
     shared_libs: [
         "android.hardware.graphics.bufferqueue@2.0",
         "android.hardware.tv.tuner@1.0",
         "android.hardware.tv.tuner@1.1",
+        "libbinder_ndk",
         "libandroid_runtime",
         "libcutils",
         "libfmq",
@@ -153,6 +158,7 @@
         "libmedia",
         "libnativehelper",
         "libutils",
+        "tv_tuner_aidl_interface-ndk_platform",
     ],
     defaults: [
         "libcodec2-impl-defaults",
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 72dc32e..440d5bc 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1172,7 +1172,7 @@
 
 sp<ITuner> JTuner::mTuner;
 sp<::android::hardware::tv::tuner::V1_1::ITuner> JTuner::mTuner_1_1;
-int JTuner::mTunerVersion = 0;
+sp<TunerClient> JTuner::mTunerClient;
 
 JTuner::JTuner(JNIEnv *env, jobject thiz)
     : mClass(NULL) {
@@ -1181,9 +1181,13 @@
 
     mClass = (jclass)env->NewGlobalRef(clazz);
     mObject = env->NewWeakGlobalRef(thiz);
+    // TODO: remove after migrate to client lib
     if (mTuner == NULL) {
         mTuner = getTunerService();
     }
+    if (mTunerClient == NULL) {
+        mTunerClient = new TunerClient();
+    }
 }
 
 JTuner::~JTuner() {
@@ -1198,13 +1202,13 @@
     env->DeleteWeakGlobalRef(mObject);
     env->DeleteGlobalRef(mClass);
     mTuner = NULL;
+    mTunerClient = NULL;
     mClass = NULL;
     mObject = NULL;
 }
 
 sp<ITuner> JTuner::getTunerService() {
     if (mTuner == nullptr) {
-        mTunerVersion = 0;
         mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
 
         if (mTuner_1_1 == nullptr) {
@@ -1212,12 +1216,9 @@
             mTuner = ITuner::getService();
             if (mTuner == nullptr) {
                 ALOGW("Failed to get tuner 1.0 service.");
-            } else {
-                mTunerVersion = 1 << 16;
             }
         } else {
             mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
-            mTunerVersion = ((1 << 16) | 1);
          }
      }
      return mTuner;
@@ -1225,15 +1226,13 @@
 
 jint JTuner::getTunerVersion() {
     ALOGD("JTuner::getTunerVersion()");
-    return (jint) mTunerVersion;
+    return (jint) mTunerClient->getHalTunerVersion();
 }
 
 jobject JTuner::getFrontendIds() {
     ALOGD("JTuner::getFrontendIds()");
-    mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
-        mFeIds = frontendIds;
-    });
-    if (mFeIds.size() == 0) {
+    vector<FrontendId> ids = mTunerClient->getFrontendIds();
+    if (ids.size() == 0) {
         ALOGW("Frontend isn't available");
         return NULL;
     }
@@ -1246,8 +1245,8 @@
     jclass integerClazz = env->FindClass("java/lang/Integer");
     jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
 
-    for (int i=0; i < mFeIds.size(); i++) {
-       jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
+    for (int i=0; i < ids.size(); i++) {
+       jobject idObj = env->NewObject(integerClazz, intInit, ids[i]);
        env->CallBooleanMethod(obj, arrayListAdd, idObj);
     }
     return obj;
@@ -1284,14 +1283,6 @@
             (jint) jId);
 }
 
-jint JTuner::closeFrontendById(int id) {
-    if (mFe != NULL && mFeId == id) {
-        Result r = mFe->close();
-        return (jint) r;
-    }
-    return (jint) Result::SUCCESS;
-}
-
 jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
@@ -1402,37 +1393,26 @@
     jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendCapabilities");
     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V");
 
-    if (mTuner_1_1 == NULL) {
-        ALOGD("1.1 Tuner is not found. Dtmb Frontend Caps are not supported.");
+    shared_ptr<FrontendDtmbCapabilities> dtmbCaps = mTunerClient->getFrontendDtmbCapabilities(id);
+    if (dtmbCaps == NULL) {
         return NULL;
     }
 
-    Result result;
-    FrontendDtmbCapabilities dtmbCaps;
-    mTuner_1_1->getFrontendDtmbCapabilities(id,
-            [&](Result r, const FrontendDtmbCapabilities& caps) {
-        dtmbCaps = caps;
-        result = r;
-    });
-    jint modulationCap = dtmbCaps.modulationCap;
-    jint transmissionModeCap = dtmbCaps.transmissionModeCap;
-    jint guardIntervalCap = dtmbCaps.guardIntervalCap;
-    jint interleaveModeCap = dtmbCaps.interleaveModeCap;
-    jint codeRateCap = dtmbCaps.codeRateCap;
-    jint bandwidthCap = dtmbCaps.bandwidthCap;
+    jint modulationCap = dtmbCaps->modulationCap;
+    jint transmissionModeCap = dtmbCaps->transmissionModeCap;
+    jint guardIntervalCap = dtmbCaps->guardIntervalCap;
+    jint interleaveModeCap = dtmbCaps->interleaveModeCap;
+    jint codeRateCap = dtmbCaps->codeRateCap;
+    jint bandwidthCap = dtmbCaps->bandwidthCap;
 
     return env->NewObject(clazz, capsInit, modulationCap, transmissionModeCap, guardIntervalCap,
             interleaveModeCap, codeRateCap, bandwidthCap);
 }
 
 jobject JTuner::getFrontendInfo(int id) {
-    FrontendInfo feInfo;
-    Result res;
-    mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
-        feInfo = info;
-        res = r;
-    });
-    if (res != Result::SUCCESS) {
+    shared_ptr<FrontendInfo> feInfo;
+    feInfo = mTunerClient->getFrontendInfo(id);
+    if (feInfo == NULL) {
         return NULL;
     }
 
@@ -1441,30 +1421,27 @@
     jmethodID infoInit = env->GetMethodID(clazz, "<init>",
             "(IIIIIIII[ILandroid/media/tv/tuner/frontend/FrontendCapabilities;)V");
 
-    jint type = (jint) feInfo.type;
-    jint minFrequency = feInfo.minFrequency;
-    jint maxFrequency = feInfo.maxFrequency;
-    jint minSymbolRate = feInfo.minSymbolRate;
-    jint maxSymbolRate = feInfo.maxSymbolRate;
-    jint acquireRange = feInfo.acquireRange;
-    jint exclusiveGroupId = feInfo.exclusiveGroupId;
-    jintArray statusCaps = env->NewIntArray(feInfo.statusCaps.size());
+    jint type = (jint) feInfo->type;
+    jint minFrequency = feInfo->minFrequency;
+    jint maxFrequency = feInfo->maxFrequency;
+    jint minSymbolRate = feInfo->minSymbolRate;
+    jint maxSymbolRate = feInfo->maxSymbolRate;
+    jint acquireRange = feInfo->acquireRange;
+    jint exclusiveGroupId = feInfo->exclusiveGroupId;
+    jintArray statusCaps = env->NewIntArray(feInfo->statusCaps.size());
     env->SetIntArrayRegion(
-            statusCaps, 0, feInfo.statusCaps.size(),
-            reinterpret_cast<jint*>(&feInfo.statusCaps[0]));
-    FrontendInfo::FrontendCapabilities caps = feInfo.frontendCaps;
+            statusCaps, 0, feInfo->statusCaps.size(),
+            reinterpret_cast<jint*>(&feInfo->statusCaps[0]));
+    FrontendInfo::FrontendCapabilities caps = feInfo->frontendCaps;
 
     jobject jcaps = NULL;
 
-    if (feInfo.type == static_cast<FrontendType>(
+    if (feInfo->type == static_cast<FrontendType>(
             ::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
-        if (mTuner_1_1 == NULL) {
-            return NULL;
-        }
         jcaps = getDtmbFrontendCaps(env, id);
     }
 
-    switch(feInfo.type) {
+    switch(feInfo->type) {
         case FrontendType::ANALOG:
             if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps
                     == caps.getDiscriminator()) {
@@ -3426,13 +3403,6 @@
     return tuner->openFrontendById(id);
 }
 
-static jint android_media_tv_Tuner_close_frontend_by_handle(
-        JNIEnv *env, jobject thiz, jint handle) {
-    sp<JTuner> tuner = getTuner(env, thiz);
-    uint32_t id = getResourceIdFromHandle(handle);
-    return tuner->closeFrontendById(id);
-}
-
 static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
     sp<JTuner> tuner = getTuner(env, thiz);
     FrontendSettings setting = getFrontendSettings(env, type, settings);
@@ -4746,8 +4716,6 @@
             (void *)android_media_tv_Tuner_get_frontend_ids },
     { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
             (void *)android_media_tv_Tuner_open_frontend_by_handle },
-    { "nativeCloseFrontendByHandle", "(I)I",
-            (void *)android_media_tv_Tuner_close_frontend_by_handle },
     { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
             (void *)android_media_tv_Tuner_tune },
     { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index e79b5c2..bec834c 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -34,6 +34,7 @@
 #include <utils/Mutex.h>
 #include <utils/RefBase.h>
 
+#include "tuner/TunerClient.h"
 #include "jni.h"
 
 using ::android::hardware::EventFlag;
@@ -76,7 +77,6 @@
 using ::android::hardware::tv::tuner::V1_1::DemuxFilterMonitorEvent;
 using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
 using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
-using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
 
 using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
@@ -259,10 +259,7 @@
     jweak mObject;
     static sp<ITuner> mTuner;
     static sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
-    // An integer that carries the Tuner version. The high 16 bits are the major version number
-    // while the low 16 bits are the minor version. Default value is unknown version 0.
-    static int mTunerVersion;
-    hidl_vec<FrontendId> mFeIds;
+    static sp<TunerClient> mTunerClient;
     sp<IFrontend> mFe;
     sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1;
     int mFeId;
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
new file mode 100644
index 0000000..11acb5e
--- /dev/null
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FrontendClient"
+
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "DemuxClient.h"
+
+using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
+
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+namespace android {
+
+/////////////// DemuxClient ///////////////////////
+
+// TODO: pending aidl interface
+DemuxClient::DemuxClient() {
+    //mTunerDemux = tunerDemux;
+}
+
+DemuxClient::~DemuxClient() {
+    //mTunerDemux = NULL;
+    mDemux = NULL;
+}
+
+// TODO: remove after migration to Tuner Service is done.
+void DemuxClient::setHidlDemux(sp<IDemux> demux) {
+    mDemux = demux;
+}
+
+Result DemuxClient::setFrontendDataSource(sp<FrontendClient> frontendClient) {
+    // TODO: pending aidl interface
+    /*if (mTunerDemux != NULL) {
+        // TODO: handle error message
+        mTunerDemux->setFrontendDataSource(frontendClient->getAidlFrontend());
+        return (int) Result::SUCCESS;
+    }*/
+
+    if (mDemux != NULL) {
+        Result res = mDemux->setFrontendDataSource(frontendClient->getId());
+        return res;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+sp<FilterClient> DemuxClient::openFilter(DemuxFilterType type, int bufferSize,
+        sp<FilterClientCallback> cb) {
+    // TODO: pending aidl interface
+
+    if (mDemux != NULL) {
+        sp<HidlFilterCallback> callback = new HidlFilterCallback(cb);
+        sp<IFilter> hidlFilter = openHidlFilter(type, bufferSize, callback);
+        if (hidlFilter != NULL) {
+            sp<FilterClient> filterClient = new FilterClient();
+            filterClient->setHidlFilter(hidlFilter);
+            return filterClient;
+        }
+    }
+
+    // TODO: handle share av memory handle
+
+    return NULL;
+}
+
+int DemuxClient::getAvSyncHwId(sp<FilterClient> filterClient) {
+    // pending aidl interface
+
+    if (mDemux != NULL) {
+        uint32_t avSyncHwId;
+        Result res;
+        sp<IFilter> halFilter = filterClient->getHalFilter();
+        mDemux->getAvSyncHwId(halFilter,
+                [&](Result r, uint32_t id) {
+                    res = r;
+                    avSyncHwId = id;
+                });
+        if (res == Result::SUCCESS) {
+            return (int) avSyncHwId;
+        }
+    }
+
+    return -1;
+}
+
+long DemuxClient::getAvSyncTime(int avSyncHwId) {
+    // pending aidl interface
+
+    if (mDemux != NULL) {
+        uint64_t time;
+        Result res;
+        mDemux->getAvSyncTime(static_cast<uint32_t>(avSyncHwId),
+                [&](Result r, uint64_t ts) {
+                    res = r;
+                    time = ts;
+                });
+        if (res == Result::SUCCESS) {
+            return (long) time;
+        }
+    }
+
+    return -1;
+}
+
+//DvrClient openDvr(int dvbType, int bufferSize, DvrClientCallback cb);
+
+Result DemuxClient::connectCiCam(int ciCamId) {
+    // pending aidl interface
+
+    if (mDemux != NULL) {
+        return mDemux->connectCiCam(static_cast<uint32_t>(ciCamId));
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result DemuxClient::disconnectCiCam() {
+    // pending aidl interface
+
+    if (mDemux != NULL) {
+        return mDemux->disconnectCiCam();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result DemuxClient::close() {
+    // pending aidl interface
+
+    if (mDemux != NULL) {
+        Result res = mDemux->close();
+        if (res == Result::SUCCESS) {
+            mDemux = NULL;
+        }
+        return res;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+/////////////// DemuxClient Helper Methods ///////////////////////
+
+sp<IFilter> DemuxClient::openHidlFilter(DemuxFilterType type, int bufferSize,
+        sp<HidlFilterCallback> callback) {
+    if (mDemux == NULL) {
+        return NULL;
+    }
+
+    sp<IFilter> hidlFilter;
+    Result res;
+    mDemux->openFilter(type, bufferSize, callback,
+            [&](Result r, const sp<IFilter>& filter) {
+                hidlFilter = filter;
+                res = r;
+            });
+    if (res != Result::SUCCESS || hidlFilter == NULL) {
+        return NULL;
+    }
+
+    return hidlFilter;
+}
+}  // namespace android
diff --git a/media/jni/tuner/DemuxClient.h b/media/jni/tuner/DemuxClient.h
new file mode 100644
index 0000000..a0671a5
--- /dev/null
+++ b/media/jni/tuner/DemuxClient.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_DEMUX_CLIENT_H_
+#define _ANDROID_MEDIA_TV_DEMUX_CLIENT_H_
+
+//#include <aidl/android/media/tv/tuner/ITunerDemux.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+
+#include "FilterClient.h"
+#include "FilterClientCallback.h"
+#include "FrontendClient.h"
+
+//using ::aidl::android::media::tv::tuner::ITunerDemux;
+
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+
+using namespace std;
+
+namespace android {
+
+struct DemuxClient : public RefBase {
+
+public:
+    DemuxClient();
+    ~DemuxClient();
+
+    // TODO: remove after migration to Tuner Service is done.
+    void setHidlDemux(sp<IDemux> demux);
+
+    /**
+     * Set a frontend resource as data input of the demux.
+     */
+    Result setFrontendDataSource(sp<FrontendClient> frontendClient);
+
+    /**
+     * Open a new filter client.
+     */
+    sp<FilterClient> openFilter(DemuxFilterType type, int bufferSize, sp<FilterClientCallback> cb);
+
+    // TODO: handle TimeFilterClient
+
+    /**
+     * Get hardware sync ID for audio and video.
+     */
+    int getAvSyncHwId(sp<FilterClient> filterClient);
+
+    /**
+     * Get current time stamp to use for A/V sync.
+     */
+    long getAvSyncTime(int avSyncHwId);
+
+    /**
+     * Open a DVR (Digital Video Record) client.
+     */
+    // TODO: handle DvrClient and callback
+    //DvrClient openDvr(int dvbType, int bufferSize, DvrClientCallback cb);  
+
+    /**
+     * Connect Conditional Access Modules (CAM) through Common Interface (CI).
+     */
+    Result connectCiCam(int ciCamId);
+
+    /**
+     * Disconnect Conditional Access Modules (CAM).
+     */
+    Result disconnectCiCam();
+
+    /**
+     * Release the Demux Client.
+     */
+    Result close();
+
+private:
+    sp<IFilter> openHidlFilter(DemuxFilterType type, int bufferSize, sp<HidlFilterCallback> cb);
+
+    /**
+     * An AIDL Tuner Demux Singleton assigned at the first time the Tuner Client
+     * opens a demux. Default null when demux is not opened.
+     */
+    // TODO: pending on aidl interface
+    //shared_ptr<ITunerDemux> mTunerDemux;
+
+    /**
+     * A Demux HAL interface that is ready before migrating to the TunerDemux.
+     * This is a temprary interface before Tuner Framework migrates to use TunerService.
+     * Default null when the HAL service does not exist.
+     */
+    sp<IDemux> mDemux;
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_DEMUX_CLIENT_H_
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
new file mode 100644
index 0000000..a71cae60
--- /dev/null
+++ b/media/jni/tuner/FilterClient.cpp
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FilterClient"
+
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "FilterClient.h"
+
+using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
+
+namespace android {
+
+/////////////// FilterClient ///////////////////////
+
+// TODO: pending aidl interface
+// TODO: add filter callback
+FilterClient::FilterClient() {
+    //mTunerFilter = tunerFilter;
+}
+
+FilterClient::~FilterClient() {
+    //mTunerFilter = NULL;
+    mFilter = NULL;
+    mFilter_1_1 = NULL;
+}
+
+// TODO: remove after migration to Tuner Service is done.
+void FilterClient::setHidlFilter(sp<IFilter> filter) {
+    mFilter = filter;
+    mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter);
+}
+
+int FilterClient::read(uint8_t* buffer, int size) {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        Result res = getFilterMq();
+        if (res != Result::SUCCESS) {
+            return -1;
+        }
+        return copyData(buffer, size);
+    }
+
+    return -1;
+}
+
+Result FilterClient::configure(DemuxFilterSettings configure) {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->configure(configure);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::configureMonitorEvent(int monitorEventType) {
+    // TODO: pending aidl interface
+
+    if (mFilter_1_1 != NULL) {
+        return mFilter_1_1->configureMonitorEvent(monitorEventType);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::configureIpFilterContextId(int cid) {
+    // TODO: pending aidl interface
+
+    if (mFilter_1_1 != NULL) {
+        return mFilter_1_1->configureIpCid(cid);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::configureAvStreamType(AvStreamType avStreamType) {
+    // TODO: pending aidl interface
+
+    if (mFilter_1_1 != NULL) {
+        return mFilter_1_1->configureAvStreamType(avStreamType);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::start() {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->start();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::stop() {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->stop();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::flush() {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->flush();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::getId(uint32_t& id) {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        Result res;
+        mFilter->getId([&](Result r, uint32_t filterId) {
+            res = r;
+            id = filterId;
+        });
+        return res;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::getId64Bit(uint64_t& id) {
+    // TODO: pending aidl interface
+
+    if (mFilter_1_1 != NULL) {
+        Result res;
+        mFilter_1_1->getId64Bit([&](Result r, uint64_t filterId) {
+            res = r;
+            id = filterId;
+        });
+        return res;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::releaseAvHandle(native_handle_t* handle, uint64_t avDataId) {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->releaseAvHandle(hidl_handle(handle), avDataId);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::setDataSource(sp<FilterClient> filterClient){
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        sp<IFilter> sourceFilter = filterClient->getHalFilter();
+        if (sourceFilter == NULL) {
+            return Result::INVALID_ARGUMENT;
+        }
+        return mFilter->setDataSource(sourceFilter);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FilterClient::close() {
+    // TODO: pending aidl interface
+
+    if (mFilter != NULL) {
+        return mFilter->close();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+/////////////// IFilterCallback ///////////////////////
+
+HidlFilterCallback::HidlFilterCallback(sp<FilterClientCallback> filterClientCallback)
+        : mFilterClientCallback(filterClientCallback) {}
+
+Return<void> HidlFilterCallback::onFilterStatus(const DemuxFilterStatus status) {
+    if (mFilterClientCallback != NULL) {
+        mFilterClientCallback->onFilterStatus(status);
+    }
+    return Void();
+}
+
+Return<void> HidlFilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
+    if (mFilterClientCallback != NULL) {
+        mFilterClientCallback->onFilterEvent(filterEvent);
+    }
+    return Void();
+}
+
+Return<void> HidlFilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+        const DemuxFilterEventExt& filterEventExt) {
+    if (mFilterClientCallback != NULL) {
+        mFilterClientCallback->onFilterEvent_1_1(filterEvent, filterEventExt);
+    }
+    return Void();
+}
+
+/////////////// FilterClient Helper Methods ///////////////////////
+
+Result FilterClient::getFilterMq() {
+    if (mFilter == NULL) {
+        return Result::INVALID_STATE;
+    }
+
+    if (mFilterMQ != NULL) {
+        return Result::SUCCESS;
+    }
+
+    Result getQueueDescResult = Result::UNKNOWN_ERROR;
+    MQDescriptorSync<uint8_t> filterMQDesc;
+    mFilter->getQueueDesc(
+            [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+                filterMQDesc = desc;
+                getQueueDescResult = r;
+            });
+    if (getQueueDescResult == Result::SUCCESS) {
+        mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
+        EventFlag::createEventFlag(mFilterMQ->getEventFlagWord(), &mFilterMQEventFlag);
+    }
+    return getQueueDescResult;
+}
+
+int FilterClient::copyData(uint8_t* buffer, int size) {
+    if (mFilter == NULL || mFilterMQ == NULL || mFilterMQEventFlag == NULL) {
+        return -1;
+    }
+
+    int available = mFilterMQ->availableToRead();
+    size = min(size, available);
+
+    if (mFilterMQ->read(buffer, size)) {
+        mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+    } else {
+        return -1;
+    }
+
+    return size;
+}
+}  // namespace android
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
new file mode 100644
index 0000000..4af74b0
--- /dev/null
+++ b/media/jni/tuner/FilterClient.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_FILTER_CLIENT_H_
+#define _ANDROID_MEDIA_TV_FILTER_CLIENT_H_
+
+//#include <aidl/android/media/tv/tuner/ITunerFilter.h>
+#include <android/hardware/tv/tuner/1.1/IFilter.h>
+#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+#include <fmq/MessageQueue.h>
+
+#include "FilterClientCallback.h"
+
+//using ::aidl::android::media::tv::tuner::ITunerFilter;
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::AvStreamType;
+using ::android::hardware::tv::tuner::V1_1::IFilterCallback;
+
+using namespace std;
+
+using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+namespace android {
+
+// TODO: pending aidl interface
+/*class TunerFilterCallback : public BnTunerFilterCallback {
+
+public:
+    TunerFilterCallback(sp<FilterClientCallback> filterClientCallback);
+
+    Status onFilterEvent(vector<TunerDemuxFilterEvent> events);
+    Status onFilterStatus(int status);
+
+private:
+    sp<FilterClientCallback> mFilterClientCallback;
+};*/
+
+struct HidlFilterCallback : public IFilterCallback {
+
+public:
+    HidlFilterCallback(sp<FilterClientCallback> filterClientCallback);
+    virtual Return<void> onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+            const DemuxFilterEventExt& filterEventExt);
+    virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
+    virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+
+private:
+    sp<FilterClientCallback> mFilterClientCallback;
+};
+
+struct FilterClient : public RefBase {
+
+public:
+    // TODO: pending aidl interface
+    FilterClient();
+    ~FilterClient();
+
+    // TODO: remove after migration to Tuner Service is done.
+    void setHidlFilter(sp<IFilter> filter);
+
+    /**
+     * Read size of data from filter FMQ into buffer.
+     *
+     * @return the actual reading size. -1 if failed to read.
+     */
+    int read(uint8_t* buffer, int size);
+
+    /**
+     * Configure the filter.
+     */
+    Result configure(DemuxFilterSettings configure);
+
+    /**
+     * Configure the monitor event of the Filter.
+     */
+    Result configureMonitorEvent(int monitorEventType);
+
+    /**
+     * Configure the context id of the IP Filter.
+     */
+    Result configureIpFilterContextId(int cid);
+
+    /**
+     * Configure the stream type of the media Filter.
+     */
+    Result configureAvStreamType(AvStreamType avStreamType);
+
+    /**
+     * Start the filter.
+     */
+    Result start();
+
+    /**
+     * Stop the filter.
+     */
+    Result stop();
+
+    /**
+     * Flush the filter.
+     */
+    Result flush();
+
+    /**
+     * Get the 32-bit filter Id.
+     */
+    Result getId(uint32_t& id);
+
+    /**
+     * Get the 64-bit filter Id.
+     */
+    Result getId64Bit(uint64_t& id);
+
+    /**
+     * Release the handle reported by the HAL for AV memory.
+     */
+    Result releaseAvHandle(native_handle_t* handle, uint64_t avDataId);
+
+    /**
+     * Set the filter's data source.
+     */
+    Result setDataSource(sp<FilterClient> filterClient);
+
+    /**
+     * Get the Hal filter to build up filter linkage.
+     */
+    sp<IFilter> getHalFilter() { return mFilter; }
+
+    /**
+     * Get the Aidl filter to build up filter linkage.
+     */
+    //shared_ptr<ITunerFilter> getAidlFilter() { return mTunerFilter; }
+
+    /**
+     * Close a new interface of ITunerFilter.
+     */
+    Result close();
+
+private:
+    Result getFilterMq();
+    int copyData(uint8_t* buffer, int size);
+
+    /**
+     * An AIDL Tuner Filter Singleton assigned at the first time when the Tuner Client
+     * opens a filter. Default null when Tuner Service does not exist.
+     */
+    // TODO: pending on aidl interface
+    //shared_ptr<ITunerFilter> mTunerFilter;
+
+    /**
+     * A 1.0 Filter HAL interface that is ready before migrating to the TunerFilter.
+     * This is a temprary interface before Tuner Framework migrates to use TunerService.
+     * Default null when the HAL service does not exist.
+     */
+    sp<IFilter> mFilter;
+
+    /**
+     * A 1.1 Filter HAL interface that is ready before migrating to the TunerFilter.
+     * This is a temprary interface before Tuner Framework migrates to use TunerService.
+     * Default null when the HAL service does not exist.
+     */
+    sp<::android::hardware::tv::tuner::V1_1::IFilter> mFilter_1_1;
+
+    unique_ptr<MQ> mFilterMQ;
+    EventFlag* mFilterMQEventFlag;
+
+    sp<FilterClientCallback> mCallback;
+    //shared_ptr<TunerFilterCallback> mAidlCallback;
+    sp<HidlFilterCallback> mHidlCallback;
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_FILTER_CLIENT_H_
diff --git a/media/jni/tuner/FilterClientCallback.h b/media/jni/tuner/FilterClientCallback.h
new file mode 100644
index 0000000..94b7821
--- /dev/null
+++ b/media/jni/tuner/FilterClientCallback.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
+#define _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
+
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_1::DemuxFilterEventExt;
+
+using namespace std;
+
+namespace android {
+
+struct FilterClientCallback : public RefBase {
+    virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+            const DemuxFilterEventExt& filterEventExt);
+    virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
+    virtual void onFilterStatus(const DemuxFilterStatus status);
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_FILTER_CLIENT_CALLBACK_H_
\ No newline at end of file
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
new file mode 100644
index 0000000..44b46f0
--- /dev/null
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FrontendClient"
+
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "FrontendClient.h"
+
+using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
+
+namespace android {
+
+/////////////// FrontendClient ///////////////////////
+
+FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int frontendHandle) {
+    mTunerFrontend = tunerFrontend;
+    mAidlCallback = NULL;
+    mHidlCallback = NULL;
+    mFrontendHandle = frontendHandle;
+}
+
+FrontendClient::~FrontendClient() {
+    mTunerFrontend = NULL;
+    mFrontend = NULL;
+    mFrontend_1_1 = NULL;
+    mAidlCallback = NULL;
+    mHidlCallback = NULL;
+    mFrontendHandle = -1;
+}
+
+Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
+    if (mTunerFrontend != NULL) {
+        mAidlCallback = ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
+        mTunerFrontend->setCallback(mAidlCallback);
+        return Result::SUCCESS;
+    }
+
+    mHidlCallback = new HidlFrontendCallback(frontendClientCallback);
+    return mFrontend->setCallback(mHidlCallback);
+}
+
+void FrontendClient::setHidlFrontend(sp<IFrontend> frontend) {
+    mFrontend = frontend;
+    mFrontend_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFrontend);
+}
+
+Result FrontendClient::tune(const FrontendSettings& settings,
+        const FrontendSettingsExt1_1& settingsExt1_1) {
+    if (mTunerFrontend != NULL) {
+        // TODO: parse hidl settings to aidl settings
+        // TODO: aidl frontend settings to include Tuner HAL 1.1 settings
+        TunerFrontendSettings settings;
+        // TODO: handle error message.
+        mTunerFrontend->tune(settings);
+        return Result::SUCCESS;
+    }
+
+    Result result;
+    if (mFrontend_1_1 != NULL) {
+        result = mFrontend_1_1->tune_1_1(settings, settingsExt1_1);
+        return result;
+    }
+
+    if (mFrontend != NULL) {
+        result = mFrontend->tune(settings);
+        return result;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FrontendClient::stopTune() {
+    if (mTunerFrontend != NULL) {
+        // TODO: handle error message.
+        mTunerFrontend->stopTune();
+        return Result::SUCCESS;
+    }
+
+    if (mFrontend != NULL) {
+        Result result = mFrontend->stopTune();
+        return result;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result FrontendClient::close() {
+    if (mTunerFrontend != NULL) {
+        // TODO: handle error message.
+        mTunerFrontend->close();
+        return Result::SUCCESS;
+    }
+
+    if (mFrontend != NULL) {
+        Result result = mFrontend->close();
+        if (result == Result::SUCCESS) {
+            mFrontend = NULL;
+            mFrontend_1_1 = NULL;
+        }
+        return result;
+    }
+
+    return Result::INVALID_STATE;
+}
+
+shared_ptr<ITunerFrontend> FrontendClient::getAidlFrontend() {
+    return mTunerFrontend;
+}
+
+int FrontendClient::getId() {
+    return getResourceIdFromHandle(mFrontendHandle);
+}
+
+/////////////// TunerFrontendCallback ///////////////////////
+
+TunerFrontendCallback::TunerFrontendCallback(sp<FrontendClientCallback> frontendClientCallback)
+        : mFrontendClientCallback(frontendClientCallback) {}
+
+Status TunerFrontendCallback::onEvent(int frontendEventType) {
+    if (mFrontendClientCallback != NULL) {
+        mFrontendClientCallback->onEvent(static_cast<FrontendEventType>(frontendEventType));
+        return Status::ok();
+    }
+    return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
+}
+
+Status TunerFrontendCallback::onLocked() {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onScanStopped() {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onProgress(int /*percent*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onFrequenciesReport(const vector<int>& /*frequency*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onSymbolRates(const vector<int>& /*rates*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onHierarchy(int /*hierarchy*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onSignalType(int /*signalType*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onPlpIds(const vector<int>& /*plpIds*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onGroupIds(const vector<int>& /*groupIds*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onInputStreamIds(const vector<int>& /*inputStreamIds*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onDvbsStandard(int /*dvbsStandandard*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onAnalogSifStandard(int /*sifStandandard*/) {
+    return Status::ok();
+}
+
+Status TunerFrontendCallback::onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& /*atsc3PlpInfos*/) {
+    return Status::ok();
+}
+
+/////////////// IFrontendCallback ///////////////////////
+
+HidlFrontendCallback::HidlFrontendCallback(sp<FrontendClientCallback> frontendClientCallback)
+        : mFrontendClientCallback(frontendClientCallback) {}
+
+Return<void> HidlFrontendCallback::onEvent(FrontendEventType frontendEventType) {
+    if (mFrontendClientCallback != NULL) {
+        mFrontendClientCallback->onEvent(frontendEventType);
+    }
+    return Void();
+}
+
+Return<void> HidlFrontendCallback::onScanMessage(FrontendScanMessageType type,
+        const FrontendScanMessage& message) {
+    if (mFrontendClientCallback != NULL) {
+        mFrontendClientCallback->onScanMessage(type, message);
+    }
+    return Void();
+}
+
+Return<void> HidlFrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+        const FrontendScanMessageExt1_1& message) {
+    if (mFrontendClientCallback != NULL) {
+        mFrontendClientCallback->onScanMessageExt1_1(type, message);
+    }
+    return Void();
+}
+}  // namespace android
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
new file mode 100644
index 0000000..7db572b
--- /dev/null
+++ b/media/jni/tuner/FrontendClient.h
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_FRONTEND_CLIENT_H_
+#define _ANDROID_MEDIA_TV_FRONTEND_CLIENT_H_
+
+#include <aidl/android/media/tv/tuner/BnTunerFrontendCallback.h>
+#include <aidl/android/media/tv/tuner/ITunerFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontend.h>
+#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+
+#include "FrontendClientCallback.h"
+
+using Status = ::ndk::ScopedAStatus;
+
+using ::aidl::android::media::tv::tuner::BnTunerFrontendCallback;
+using ::aidl::android::media::tv::tuner::ITunerFrontend;
+using ::aidl::android::media::tv::tuner::TunerAtsc3PlpInfo;
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::FrontendInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
+using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
+using ::android::hardware::tv::tuner::V1_1::IFrontendCallback;
+
+using namespace std;
+
+namespace android {
+
+class TunerFrontendCallback : public BnTunerFrontendCallback {
+
+public:
+    TunerFrontendCallback(sp<FrontendClientCallback> frontendClientCallback);
+
+    Status onEvent(int frontendEventType);
+
+    Status onLocked();
+
+    Status onScanStopped();
+
+    Status onProgress(int percent);
+
+    Status onFrequenciesReport(const vector<int>& frequency);
+
+    Status onSymbolRates(const vector<int>& rates);
+
+    Status onHierarchy(int hierarchy);
+
+    Status onSignalType(int signalType);
+
+    Status onPlpIds(const vector<int>& plpIds);
+
+    Status onGroupIds(const vector<int>& groupIds);
+
+    Status onInputStreamIds(const vector<int>& inputStreamIds);
+
+    Status onDvbsStandard(int dvbsStandandard);
+
+    Status onAnalogSifStandard(int sifStandandard);
+
+    Status onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& atsc3PlpInfos);
+
+private:
+    sp<FrontendClientCallback> mFrontendClientCallback;
+};
+
+struct HidlFrontendCallback : public IFrontendCallback {
+
+public:
+    HidlFrontendCallback(sp<FrontendClientCallback> frontendClientCallback);
+
+    virtual Return<void> onEvent(FrontendEventType frontendEventType);
+    virtual Return<void> onScanMessage(
+            FrontendScanMessageType type, const FrontendScanMessage& message);
+    virtual Return<void> onScanMessageExt1_1(
+            FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
+
+private:
+    sp<FrontendClientCallback> mFrontendClientCallback;
+};
+
+struct FrontendClient : public RefBase {
+
+public:
+    FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int frontendHandle);
+    ~FrontendClient();
+
+    /**
+     * Set a FrontendClientCallback to receive frontend events and scan messages.
+     */
+    Result setCallback(sp<FrontendClientCallback> frontendClientCallback);
+
+    // TODO: remove after migration to Tuner Service is done.
+    void setHidlFrontend(sp<IFrontend> frontend);
+
+    /**
+     * Tuner Frontend with Frontend Settings.
+     */
+    Result tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
+
+    /**
+     * Stop tune Frontend.
+     */
+    Result stopTune();
+
+    /**
+     * Close Frontend.
+     */
+    Result close();
+
+    shared_ptr<ITunerFrontend> getAidlFrontend();
+
+    int getId();
+
+    static int getResourceIdFromHandle(int handle) {
+        return (handle & 0x00ff0000) >> 16;
+    }
+
+private:
+    /**
+     * An AIDL Tuner Frontend Singleton assigned at the first time when the Tuner Client
+     * opens a frontend cient. Default null when the service does not exist.
+     */
+    shared_ptr<ITunerFrontend> mTunerFrontend;
+
+    /**
+     * A Frontend 1.0 HAL interface as a fall back interface when the Tuner Service does not exist.
+     * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
+     * Default null.
+     */
+    sp<IFrontend> mFrontend;
+
+    /**
+     * A Frontend 1.1 HAL interface as a fall back interface when the Tuner Service does not exist.
+     * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
+     * Default null.
+     */
+    sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
+
+    shared_ptr<TunerFrontendCallback> mAidlCallback;
+    sp<HidlFrontendCallback> mHidlCallback;
+
+    int mFrontendHandle;
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_FRONTEND_CLIENT_H_
diff --git a/media/jni/tuner/FrontendClientCallback.h b/media/jni/tuner/FrontendClientCallback.h
new file mode 100644
index 0000000..94f8c40
--- /dev/null
+++ b/media/jni/tuner/FrontendClientCallback.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_FRONTEND_CLIENT_CALLBACK_H_
+#define _ANDROID_MEDIA_TV_FRONTEND_CLIENT_CALLBACK_H_
+
+using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageExt1_1;
+using ::android::hardware::tv::tuner::V1_1::FrontendScanMessageTypeExt1_1;
+
+using namespace std;
+
+namespace android {
+
+struct FrontendClientCallback : public RefBase {
+    virtual void onEvent(FrontendEventType frontendEventType);
+    virtual void onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message);
+    virtual void onScanMessageExt1_1(
+            FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_FRONTEND_CLIENT_CALLBACK_H_
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
new file mode 100644
index 0000000..a56a418
--- /dev/null
+++ b/media/jni/tuner/TunerClient.cpp
@@ -0,0 +1,236 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "TunerClient"
+
+#include <android/binder_manager.h>
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "TunerClient.h"
+
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendType;
+
+namespace android {
+
+sp<ITuner> TunerClient::mTuner;
+sp<::android::hardware::tv::tuner::V1_1::ITuner> TunerClient::mTuner_1_1;
+shared_ptr<ITunerService> TunerClient::mTunerService;
+int TunerClient::mTunerVersion;
+
+/////////////// TunerClient ///////////////////////
+
+TunerClient::TunerClient() {
+    // Get HIDL Tuner in migration stage.
+    getHidlTuner();
+    // Connect with Tuner Service.
+    ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
+    mTunerService = ITunerService::fromBinder(binder);
+    if (mTunerService == NULL) {
+        ALOGE("Failed to get tuner service");
+    }
+}
+
+TunerClient::~TunerClient() {
+    mTuner = NULL;
+    mTuner_1_1 = NULL;
+    mTunerVersion = 0;
+    mTunerService = NULL;
+}
+
+vector<FrontendId> TunerClient::getFrontendIds() {
+    vector<FrontendId> ids;
+    // TODO: pending aidl interface
+    /*if (mTunerService != NULL) {
+        return mTunerService->getFrontendIds();
+    }*/
+
+    if (mTuner != NULL) {
+        Result res;
+        mTuner->getFrontendIds([&](Result r, const hardware::hidl_vec<FrontendId>& frontendIds) {
+            res = r;
+            ids = frontendIds;
+        });
+        if (res != Result::SUCCESS || ids.size() == 0) {
+            ALOGW("Frontend ids not available");
+            ids.clear();
+            return ids;
+        }
+        return ids;
+    }
+
+    return ids;
+}
+
+
+sp<FrontendClient> TunerClient::openFrontend(int frontendHandle) {
+    if (mTunerService != NULL) {
+        // TODO: handle error code
+        shared_ptr<ITunerFrontend> tunerFrontend;
+        mTunerService->openFrontend(frontendHandle, &tunerFrontend);
+        return new FrontendClient(tunerFrontend, frontendHandle);
+    }
+
+    if (mTuner != NULL) {
+        sp<IFrontend> hidlFrontend = openHidlFrontendByHandle(frontendHandle);
+        if (hidlFrontend != NULL) {
+            sp<FrontendClient> frontendClient = new FrontendClient(NULL, frontendHandle);
+            frontendClient->setHidlFrontend(hidlFrontend);
+            return frontendClient;
+        }
+    }
+
+    return NULL;
+}
+
+shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) {
+    if (mTunerService != NULL) {
+        TunerServiceFrontendInfo aidlFrontendInfo;
+        // TODO: handle error code
+        mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
+        return make_shared<FrontendInfo>(FrontendInfoAidlToHidl(aidlFrontendInfo));
+    }
+
+    if (mTuner != NULL) {
+        FrontendInfo hidlInfo;
+        Result res = getHidlFrontendInfo(id, hidlInfo);
+        if (res != Result::SUCCESS) {
+            return NULL;
+        }
+        return make_shared<FrontendInfo>(hidlInfo);
+    }
+
+    return NULL;
+}
+
+shared_ptr<FrontendDtmbCapabilities> TunerClient::getFrontendDtmbCapabilities(int id) {
+    // pending aidl interface
+
+    if (mTuner_1_1 != NULL) {
+        Result result;
+        FrontendDtmbCapabilities dtmbCaps;
+        mTuner_1_1->getFrontendDtmbCapabilities(id,
+                [&](Result r, const FrontendDtmbCapabilities& caps) {
+            dtmbCaps = caps;
+            result = r;
+        });
+        if (result == Result::SUCCESS) {
+            return make_shared<FrontendDtmbCapabilities>(dtmbCaps);
+        }
+    }
+
+    return NULL;
+}
+
+sp<DemuxClient> TunerClient::openDemux(int /*demuxHandle*/) {
+    if (mTunerService != NULL) {
+        // TODO: handle error code
+        /*shared_ptr<ITunerDemux> tunerDemux;
+        mTunerService->openDemux(demuxHandle, &tunerDemux);
+        return new DemuxClient(tunerDemux);*/
+    }
+
+    if (mTuner != NULL) {
+        // TODO: pending aidl interface
+        sp<DemuxClient> demuxClient = new DemuxClient();
+        sp<IDemux> hidlDemux = openHidlDemux();
+        if (hidlDemux != NULL) {
+            demuxClient->setHidlDemux(hidlDemux);
+            return demuxClient;
+        }
+    }
+
+    return NULL;
+}
+
+/////////////// TunerClient Helper Methods ///////////////////////
+
+sp<ITuner> TunerClient::getHidlTuner() {
+    if (mTuner == NULL) {
+        mTunerVersion = 0;
+        mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
+
+        if (mTuner_1_1 == NULL) {
+            ALOGW("Failed to get tuner 1.1 service.");
+            mTuner = ITuner::getService();
+            if (mTuner == NULL) {
+                ALOGW("Failed to get tuner 1.0 service.");
+            } else {
+                mTunerVersion = 1 << 16;
+            }
+        } else {
+            mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
+            mTunerVersion = ((1 << 16) | 1);
+         }
+     }
+     return mTuner;
+}
+
+sp<IFrontend> TunerClient::openHidlFrontendByHandle(int frontendHandle) {
+    sp<IFrontend> fe;
+    Result res;
+    uint32_t id = getResourceIdFromHandle(frontendHandle);
+    mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
+        fe = frontend;
+        res = r;
+    });
+    if (res != Result::SUCCESS || fe == nullptr) {
+        ALOGE("Failed to open frontend");
+        return NULL;
+    }
+    return fe;
+}
+
+Result TunerClient::getHidlFrontendInfo(int id, FrontendInfo& feInfo) {
+    Result res;
+    mTuner->getFrontendInfo(id, [&](Result r, const FrontendInfo& info) {
+        feInfo = info;
+        res = r;
+    });
+    return res;
+}
+
+sp<IDemux> TunerClient::openHidlDemux() {
+    sp<IDemux> demux;
+    Result res;
+
+    mTuner->openDemux([&](Result result, uint32_t /*id*/, const sp<IDemux>& demuxSp) {
+        demux = demuxSp;
+        res = result;
+    });
+    if (res != Result::SUCCESS || demux == nullptr) {
+        ALOGE("Failed to open demux");
+        return NULL;
+    }
+    return demux;
+}
+
+FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) {
+    FrontendInfo hidlFrontendInfo {
+        .type = static_cast<FrontendType>(aidlFrontendInfo.type),
+        .minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
+        .maxFrequency = static_cast<uint32_t>(aidlFrontendInfo.maxFrequency),
+        .minSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.minSymbolRate),
+        .maxSymbolRate = static_cast<uint32_t>(aidlFrontendInfo.maxSymbolRate),
+        .acquireRange = static_cast<uint32_t>(aidlFrontendInfo.acquireRange),
+        .exclusiveGroupId = static_cast<uint32_t>(aidlFrontendInfo.exclusiveGroupId),
+    };
+    // TODO: handle Frontend caps
+
+    return hidlFrontendInfo;
+}
+}  // namespace android
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
new file mode 100644
index 0000000..197b110
--- /dev/null
+++ b/media/jni/tuner/TunerClient.h
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
+#define _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
+
+#include <aidl/android/media/tv/tuner/ITunerService.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+
+#include "FrontendClient.h"
+#include "DemuxClient.h"
+
+using ::aidl::android::media::tv::tuner::ITunerService;
+using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+
+using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
+
+using namespace std;
+
+namespace android {
+
+struct TunerClient : public RefBase {
+
+public:
+    TunerClient();
+    ~TunerClient();
+
+    /**
+     * Retrieve all the frontend ids.
+     *
+     * @return a list of the available frontend ids
+     */
+    vector<FrontendId> getFrontendIds();
+
+    /**
+     * Open a new interface of FrontendClient given a frontendHandle.
+     *
+     * @param frontendHandle the handle of the frontend granted by TRM.
+     * @return a newly created FrontendClient interface.
+     */
+    sp<FrontendClient> openFrontend(int frontendHandle);
+
+    /**
+     * Retrieve the granted frontend's information.
+     *
+     * @param id the id of the frontend granted by TRM.
+     * @return the information for the frontend.
+     */
+    shared_ptr<FrontendInfo> getFrontendInfo(int id);
+
+    /**
+     * Retrieve the DTMB frontend's capabilities.
+     *
+     * @param id the id of the DTMB frontend.
+     * @return the capabilities of the frontend.
+     */
+    shared_ptr<FrontendDtmbCapabilities> getFrontendDtmbCapabilities(int id);
+
+    /**
+     * Open a new interface of DemuxClient given a demuxHandle.
+     *
+     * @param demuxHandle the handle of the demux granted by TRM.
+     * @return a newly created DemuxClient interface.
+     */
+    sp<DemuxClient> openDemux(int demuxHandle);
+
+    /**
+     * Retrieve the Demux capabilities.
+     *
+     * @return the demux’s capabilities.
+     */
+    //DemuxCapabilities getDemuxCaps() {};
+
+    /**
+     * Get the current Tuner HAL version. The high 16 bits are the major version number
+     * while the low 16 bits are the minor version. Default value is unknown version 0.
+     */
+    int getHalTunerVersion() { return mTunerVersion; }
+
+    static int getResourceIdFromHandle(int handle) {
+        return (handle & 0x00ff0000) >> 16;
+    }
+
+private:
+    /**
+     * An AIDL Tuner Service Singleton assigned at the first time the Tuner Client
+     * connects with the Tuner Service. Default null when the service does not exist.
+     */
+    static shared_ptr<ITunerService> mTunerService;
+
+    /**
+     * A Tuner 1.0 HAL interface that is ready before connecting to the TunerService
+     * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
+     * Default null.
+     */
+    static sp<ITuner> mTuner;
+
+    /**
+     * A Tuner 1.1 HAL interface that is ready before connecting to the TunerService
+     * This is a temprary connection before the Tuner Framework fully migrates to the TunerService.
+     * Default null.
+     */
+    static sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
+
+    // An integer that carries the Tuner version. The high 16 bits are the major version number
+    // while the low 16 bits are the minor version. Default value is unknown version 0.
+    static int mTunerVersion;
+
+    sp<ITuner> getHidlTuner();
+    sp<IFrontend> openHidlFrontendByHandle(int frontendHandle);
+    sp<IDemux> openHidlDemux();
+    Result getHidlFrontendInfo(int id, FrontendInfo& info);
+    FrontendInfo FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo);
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
diff --git a/media/tests/MtpTests/src/android/mtp/MtpDatabaseTest.java b/media/tests/MtpTests/src/android/mtp/MtpDatabaseTest.java
index e2e8ff4..dfbafe4 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpDatabaseTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpDatabaseTest.java
@@ -132,7 +132,7 @@
 
         StorageVolume mainStorage = new StorageVolume(MAIN_STORAGE_ID_STR,
                 mMainStorageDir, mMainStorageDir, "Primary Storage",
-				true, false, true, false, -1, UserHandle.CURRENT, "", "");
+                true, false, true, false, -1, UserHandle.CURRENT, null /* uuid */, "", "");
 
         final StorageVolume primary = mainStorage;
 
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index 1f58bde..fdf6582 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -132,9 +132,10 @@
         secondaryStorageDir = createNewDir(TEMP_DIR_FILE);
 
         StorageVolume mainStorage = new StorageVolume("1", mainStorageDir, mainStorageDir,
-                "", true, false, true, false, -1, UserHandle.CURRENT, "", "");
+                "", true, false, true, false, -1, UserHandle.CURRENT, null /* uuid */, "", "");
         StorageVolume secondaryStorage = new StorageVolume("2", secondaryStorageDir,
-                secondaryStorageDir, "", false, false, true, false, -1, UserHandle.CURRENT, "", "");
+                secondaryStorageDir, "", false, false, true, false, -1, UserHandle.CURRENT,
+                null /* uuid */, "", "");
 
         objectsAdded = new ArrayList<>();
         objectsRemoved = new ArrayList<>();
diff --git a/media/tests/TunerTest/Android.bp b/media/tests/TunerTest/Android.bp
index e865604..5c3e9ab 100644
--- a/media/tests/TunerTest/Android.bp
+++ b/media/tests/TunerTest/Android.bp
@@ -10,6 +10,7 @@
 
     static_libs: [
         "androidx.test.rules",
+        "compatibility-device-util-axt",
         "testng"
     ],
 
diff --git a/media/tests/TunerTest/AndroidManifest.xml b/media/tests/TunerTest/AndroidManifest.xml
index ec155ca..cf63f50 100644
--- a/media/tests/TunerTest/AndroidManifest.xml
+++ b/media/tests/TunerTest/AndroidManifest.xml
@@ -17,7 +17,12 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.mediatunertest">
 
+    <uses-permission android:name="android.permission.ACCESS_TV_DESCRAMBLER" />
     <uses-permission android:name="android.permission.ACCESS_TV_TUNER" />
+    <uses-permission android:name="android.permission.CREATE_USERS"/>
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
+    <uses-permission android:name="android.permission.MANAGE_USERS"/>
+    <uses-permission android:name="android.permission.TUNER_RESOURCE_ACCESS" />
 
     <application android:label="@string/app_name">
         <uses-library android:name="android.test.runner" />
diff --git a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
index de7f7eb..22542d5 100644
--- a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
+++ b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
@@ -19,6 +19,8 @@
 import static org.junit.Assert.assertNotNull;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.tv.TvInputService;
 import android.media.tv.tuner.Descrambler;
 import android.media.tv.tuner.Tuner;
 
@@ -26,16 +28,24 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.RequiredFeatureRule;
+
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+// TODO: (b/174500129) add TEST_MAPPING on TunerTest when TunerService is ready
 public class TunerTest {
     private static final String TAG = "MediaTunerTest";
 
+    @Rule
+    public RequiredFeatureRule featureRule = new RequiredFeatureRule(
+            PackageManager.FEATURE_TUNER);
+
     private Context mContext;
 
     @Before
@@ -49,13 +59,15 @@
 
     @Test
     public void testTunerConstructor() throws Exception {
-        Tuner tuner = new Tuner(mContext, "123", 1);
+        Tuner tuner = new Tuner(mContext, null,
+                TvInputService.PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND);
         assertNotNull(tuner);
     }
 
     @Test
     public void testOpenDescrambler() throws Exception {
-        Tuner tuner = new Tuner(mContext, "123", 1);
+        Tuner tuner = new Tuner(mContext, null,
+                TvInputService.PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND);
         Descrambler descrambler = tuner.openDescrambler();
         assertNotNull(descrambler);
     }
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 4473610..3e65df2 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -48,6 +48,7 @@
             android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
             android:label="@string/action_bar_label"
             android:exported="true"
+            android:permission="android.permission.MODIFY_PHONE_STATE"
             android:theme="@style/AppTheme"
             android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 082c148..3b7775a 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -57,7 +57,6 @@
     <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
       <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvées</item>
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -78,7 +77,6 @@
     <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
       <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
-      <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
       <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
     </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> en cours…"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 560c5dc..f6e901d 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -57,7 +57,6 @@
     <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
       <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes trouvées</item>
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -78,7 +77,6 @@
     <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
       <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
-      <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
       <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
     </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
diff --git a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_e_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_e_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_e_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_h_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_h_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml b/packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml
rename to packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc004/strings.xml
similarity index 100%
rename from packages/SystemUI/res/values-mcc310-mnc004/strings.xml
rename to packages/SettingsLib/res/values-mcc310-mnc004/strings.xml
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc480/strings.xml
similarity index 100%
rename from packages/SystemUI/res/values-mcc311-mnc480/strings.xml
rename to packages/SettingsLib/res/values-mcc311-mnc480/strings.xml
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 332d6c7..45253bb 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -21,4 +21,11 @@
 
     <!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V  -->
     <integer name="config_chargingFastThreshold">7500000</integer>
+
+    <!-- When true, show 1/2G networks as 3G. -->
+    <bool name="config_showMin3G">false</bool>
+
+    <!-- Control whether status bar should distinguish HSPA data icon form UMTS
+    data icon on devices -->
+    <bool name="config_hspa_data_distinguishable">false</bool>
 </resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index ca06867..f518b74 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1404,4 +1404,79 @@
     <string name="wifi_hotspot_switch_on_text">On</string>
     <!-- Label for Wifi hotspot switch off. Toggles hotspot off [CHAR LIMIT=30] -->
     <string name="wifi_hotspot_switch_off_text">Off</string>
+
+    <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] -->
+    <string name="carrier_network_change_mode">Carrier network changing</string>
+
+    <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_3g">3G</string>
+
+    <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_edge">EDGE</string>
+
+    <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_cdma">1X</string>
+
+    <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_gprs">GPRS</string>
+
+    <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_3_5g">H</string>
+
+    <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_3_5g_plus">H+</string>
+
+    <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
+    <string name="data_connection_4g">4G</string>
+
+    <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_4g_plus">4G+</string>
+
+    <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_lte">LTE</string>
+
+    <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_lte_plus">LTE+</string>
+
+    <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] -->
+    <string name="data_connection_5ge_html" translate="false"> &lt;i>5G &lt;small>E&lt;/small>&lt;/i> </string>
+
+    <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_5g" translatable="false">5G</string>
+
+    <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] -->
+    <string name="data_connection_5g_plus" translatable="false">5G+</string>
+
+    <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
+    <string name="cell_data_off_content_description">Mobile data off</string>
+
+    <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] -->
+    <string name="not_default_data_content_description">Not set to use data</string>
+
+    <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_phone">No phone.</string>
+    <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_one_bar">Phone one bar.</string>
+    <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_two_bars">Phone two bars.</string>
+    <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_three_bars">Phone three bars.</string>
+    <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_phone_signal_full">Phone signal full.</string>
+
+    <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_data">No data.</string>
+    <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_one_bar">Data one bar.</string>
+    <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_two_bars">Data two bars.</string>
+    <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_three_bars">Data three bars.</string>
+    <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_data_signal_full">Data signal full.</string>
+
+    <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string>
+    <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_ethernet_connected">Ethernet connected.</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
new file mode 100644
index 0000000..45028ff
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib;
+
+/**
+ * Content descriptions for accessibility support.
+ */
+public class AccessibilityContentDescriptions {
+
+    private AccessibilityContentDescriptions() {}
+    public static final int[] PHONE_SIGNAL_STRENGTH = {
+        R.string.accessibility_no_phone,
+        R.string.accessibility_phone_one_bar,
+        R.string.accessibility_phone_two_bars,
+        R.string.accessibility_phone_three_bars,
+        R.string.accessibility_phone_signal_full
+    };
+
+    public static final int[] DATA_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_data,
+        R.string.accessibility_data_one_bar,
+        R.string.accessibility_data_two_bars,
+        R.string.accessibility_data_three_bars,
+        R.string.accessibility_data_signal_full
+    };
+
+    public static final int[] WIFI_CONNECTION_STRENGTH = {
+        R.string.accessibility_no_wifi,
+        R.string.accessibility_wifi_one_bar,
+        R.string.accessibility_wifi_two_bars,
+        R.string.accessibility_wifi_three_bars,
+        R.string.accessibility_wifi_signal_full
+    };
+
+    public static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
+
+    public static final int[] ETHERNET_CONNECTION_VALUES = {
+        R.string.accessibility_ethernet_disconnected,
+        R.string.accessibility_ethernet_connected,
+    };
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
new file mode 100644
index 0000000..bc0c6f3
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
@@ -0,0 +1,224 @@
+/*
+ * 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.settingslib;
+
+import java.text.SimpleDateFormat;
+import java.util.Objects;
+
+/**
+ * Icons and states for SysUI and Settings.
+ */
+public class SignalIcon {
+
+    /**
+     * Holds icons for a given state. Arrays are generally indexed as inet
+     * state (full connectivity or not) first, and second dimension as
+     * signal strength.
+     */
+    public static class IconGroup {
+        public final int[][] sbIcons;
+        public final int[][] qsIcons;
+        public final int[] contentDesc;
+        public final int sbNullState;
+        public final int qsNullState;
+        public final int sbDiscState;
+        public final int qsDiscState;
+        public final int discContentDesc;
+        // For logging.
+        public final String name;
+
+        public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+                int discContentDesc) {
+            this.name = name;
+            this.sbIcons = sbIcons;
+            this.qsIcons = qsIcons;
+            this.contentDesc = contentDesc;
+            this.sbNullState = sbNullState;
+            this.qsNullState = qsNullState;
+            this.sbDiscState = sbDiscState;
+            this.qsDiscState = qsDiscState;
+            this.discContentDesc = discContentDesc;
+        }
+
+        @Override
+        public String toString() {
+            return "IconGroup(" + name + ")";
+        }
+    }
+
+    /**
+     * Holds states for SysUI.
+     */
+    public static class State {
+        // No locale as it's only used for logging purposes
+        private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+        public boolean connected;
+        public boolean enabled;
+        public boolean activityIn;
+        public boolean activityOut;
+        public int level;
+        public IconGroup iconGroup;
+        public int inetCondition;
+        public int rssi; // Only for logging.
+
+        // Not used for comparison, just used for logging.
+        public long time;
+
+        /**
+         * Generates a copy of the source state.
+         */
+        public void copyFrom(State state) {
+            connected = state.connected;
+            enabled = state.enabled;
+            level = state.level;
+            iconGroup = state.iconGroup;
+            inetCondition = state.inetCondition;
+            activityIn = state.activityIn;
+            activityOut = state.activityOut;
+            rssi = state.rssi;
+            time = state.time;
+        }
+
+        @Override
+        public String toString() {
+            if (time != 0) {
+                StringBuilder builder = new StringBuilder();
+                toString(builder);
+                return builder.toString();
+            } else {
+                return "Empty " + getClass().getSimpleName();
+            }
+        }
+
+        protected void toString(StringBuilder builder) {
+            builder.append("connected=").append(connected).append(',')
+                .append("enabled=").append(enabled).append(',')
+                .append("level=").append(level).append(',')
+                .append("inetCondition=").append(inetCondition).append(',')
+                .append("iconGroup=").append(iconGroup).append(',')
+                .append("activityIn=").append(activityIn).append(',')
+                .append("activityOut=").append(activityOut).append(',')
+                .append("rssi=").append(rssi).append(',')
+                .append("lastModified=").append(sSDF.format(time));
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!o.getClass().equals(getClass())) {
+                return false;
+            }
+            State other = (State) o;
+            return other.connected == connected
+                    && other.enabled == enabled
+                    && other.level == level
+                    && other.inetCondition == inetCondition
+                    && other.iconGroup == iconGroup
+                    && other.activityIn == activityIn
+                    && other.activityOut == activityOut
+                    && other.rssi == rssi;
+        }
+    }
+
+    /**
+     * Holds icons for a given MobileState.
+     */
+    public static class MobileIconGroup extends IconGroup {
+        public final int dataContentDescription; // mContentDescriptionDataType
+        public final int dataType;
+        public final boolean isWide;
+        public final int qsDataType;
+
+        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+                int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
+            super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
+                qsDiscState, discContentDesc);
+            this.dataContentDescription = dataContentDesc;
+            this.dataType = dataType;
+            this.isWide = isWide;
+            this.qsDataType = dataType; // TODO: remove this field
+        }
+    }
+
+    /**
+     * Holds mobile states for SysUI.
+     */
+    public static class MobileState extends State {
+        public String networkName;
+        public String networkNameData;
+        public boolean dataSim;
+        public boolean dataConnected;
+        public boolean isEmergency;
+        public boolean airplaneMode;
+        public boolean carrierNetworkChangeMode;
+        public boolean isDefault;
+        public boolean userSetup;
+        public boolean roaming;
+        public boolean defaultDataOff;  // Tracks the on/off state of the defaultDataSubscription
+
+        @Override
+        public void copyFrom(State s) {
+            super.copyFrom(s);
+            MobileState state = (MobileState) s;
+            dataSim = state.dataSim;
+            networkName = state.networkName;
+            networkNameData = state.networkNameData;
+            dataConnected = state.dataConnected;
+            isDefault = state.isDefault;
+            isEmergency = state.isEmergency;
+            airplaneMode = state.airplaneMode;
+            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
+            userSetup = state.userSetup;
+            roaming = state.roaming;
+            defaultDataOff = state.defaultDataOff;
+        }
+
+        @Override
+        protected void toString(StringBuilder builder) {
+            super.toString(builder);
+            builder.append(',');
+            builder.append("dataSim=").append(dataSim).append(',');
+            builder.append("networkName=").append(networkName).append(',');
+            builder.append("networkNameData=").append(networkNameData).append(',');
+            builder.append("dataConnected=").append(dataConnected).append(',');
+            builder.append("roaming=").append(roaming).append(',');
+            builder.append("isDefault=").append(isDefault).append(',');
+            builder.append("isEmergency=").append(isEmergency).append(',');
+            builder.append("airplaneMode=").append(airplaneMode).append(',');
+            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
+                    .append(',');
+            builder.append("userSetup=").append(userSetup).append(',');
+            builder.append("defaultDataOff=").append(defaultDataOff);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            return super.equals(o)
+                && Objects.equals(((MobileState) o).networkName, networkName)
+                && Objects.equals(((MobileState) o).networkNameData, networkNameData)
+                && ((MobileState) o).dataSim == dataSim
+                && ((MobileState) o).dataConnected == dataConnected
+                && ((MobileState) o).isEmergency == isEmergency
+                && ((MobileState) o).airplaneMode == airplaneMode
+                && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
+                && ((MobileState) o).userSetup == userSetup
+                && ((MobileState) o).isDefault == isDefault
+                && ((MobileState) o).roaming == roaming
+                && ((MobileState) o).defaultDataOff == defaultDataOff;
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
index 5689860..09f285b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
@@ -15,10 +15,21 @@
  */
 package com.android.settingslib.mobile;
 
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.PersistableBundle;
 import android.telephony.Annotation;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager;
 
+import com.android.settingslib.R;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Holds the utility functions to create the RAT to MobileIconGroup mappings.
  */
@@ -60,4 +71,165 @@
                 return "unsupported";
         }
     }
+
+    /**
+     * Produce the default MobileIconGroup.
+     */
+    public static MobileIconGroup getDefaultIcons(Config config) {
+        if (!config.showAtLeast3G) {
+            return TelephonyIcons.G;
+        } else {
+            return TelephonyIcons.THREE_G;
+        }
+    }
+
+    /**
+     * Produce a mapping of data network types to icon groups for simple and quick use in
+     * updateTelephony.
+     */
+    public static Map<String, MobileIconGroup> mapIconSets(Config config) {
+        final Map<String, MobileIconGroup> networkToIconLookup = new HashMap<>();
+
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0),
+                TelephonyIcons.THREE_G);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A),
+                TelephonyIcons.THREE_G);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B),
+                TelephonyIcons.THREE_G);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD),
+                TelephonyIcons.THREE_G);
+        if (config.show4gFor3g) {
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
+                    TelephonyIcons.FOUR_G);
+        } else {
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
+                    TelephonyIcons.THREE_G);
+        }
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA),
+                TelephonyIcons.THREE_G);
+
+        if (!config.showAtLeast3G) {
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
+                    TelephonyIcons.UNKNOWN);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
+                    TelephonyIcons.E);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
+                    TelephonyIcons.ONE_X);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
+                    TelephonyIcons.ONE_X);
+        } else {
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
+                    TelephonyIcons.THREE_G);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
+                    TelephonyIcons.THREE_G);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
+                    TelephonyIcons.THREE_G);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
+                    TelephonyIcons.THREE_G);
+        }
+
+        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+        MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
+        if (config.show4gFor3g) {
+            hGroup = TelephonyIcons.FOUR_G;
+            hPlusGroup = TelephonyIcons.FOUR_G;
+        } else if (config.hspaDataDistinguishable) {
+            hGroup = TelephonyIcons.H;
+            hPlusGroup = TelephonyIcons.H_PLUS;
+        }
+
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup);
+        networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup);
+
+        if (config.show4gForLte) {
+            networkToIconLookup.put(toIconKey(
+                    TelephonyManager.NETWORK_TYPE_LTE),
+                    TelephonyIcons.FOUR_G);
+            if (config.hideLtePlus) {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.FOUR_G);
+            } else {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.FOUR_G_PLUS);
+            }
+        } else {
+            networkToIconLookup.put(toIconKey(
+                    TelephonyManager.NETWORK_TYPE_LTE),
+                    TelephonyIcons.LTE);
+            if (config.hideLtePlus) {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.LTE);
+            } else {
+                networkToIconLookup.put(toDisplayIconKey(
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+                        TelephonyIcons.LTE_PLUS);
+            }
+        }
+        networkToIconLookup.put(toIconKey(
+                TelephonyManager.NETWORK_TYPE_IWLAN),
+                TelephonyIcons.WFC);
+        networkToIconLookup.put(toDisplayIconKey(
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
+                TelephonyIcons.LTE_CA_5G_E);
+        networkToIconLookup.put(toDisplayIconKey(
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
+                TelephonyIcons.NR_5G);
+        networkToIconLookup.put(toDisplayIconKey(
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE),
+                TelephonyIcons.NR_5G_PLUS);
+        networkToIconLookup.put(toIconKey(
+                TelephonyManager.NETWORK_TYPE_NR),
+                TelephonyIcons.NR_5G);
+        return networkToIconLookup;
+    }
+
+    /**
+     * Wrapper class of system configs and Carrier configs.
+     */
+    public static class Config {
+        public boolean showAtLeast3G = false;
+        public boolean show4gFor3g = false;
+        public boolean alwaysShowCdmaRssi = false;
+        public boolean show4gForLte = false;
+        public boolean hideLtePlus = false;
+        public boolean hspaDataDistinguishable;
+        public boolean alwaysShowDataRatIcon = false;
+
+        /**
+         * Reads the latest configs.
+         */
+        public static Config readConfig(Context context) {
+            Config config = new Config();
+            Resources res = context.getResources();
+
+            config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
+            config.alwaysShowCdmaRssi =
+                    res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
+            config.hspaDataDistinguishable =
+                    res.getBoolean(R.bool.config_hspa_data_distinguishable);
+
+            CarrierConfigManager configMgr = (CarrierConfigManager)
+                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            // Handle specific carrier config values for the default data SIM
+            int defaultDataSubId = SubscriptionManager.from(context)
+                    .getDefaultDataSubscriptionId();
+            PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
+            if (b != null) {
+                config.alwaysShowDataRatIcon = b.getBoolean(
+                        CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
+                config.show4gForLte = b.getBoolean(
+                        CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
+                config.show4gFor3g = b.getBoolean(
+                        CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
+                config.hideLtePlus = b.getBoolean(
+                        CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
+            }
+            return config;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
similarity index 74%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
rename to packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
index d9591cf..c2613a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
@@ -14,33 +14,37 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.settingslib.mobile;
 
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.R;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
 
 import java.util.HashMap;
 import java.util.Map;
 
-class TelephonyIcons {
+/**
+ * Telephony related icons and strings for SysUI and Settings.
+ */
+public class TelephonyIcons {
     //***** Data connection icons
-    static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
+    public static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
 
-    static final int ICON_LTE = R.drawable.ic_lte_mobiledata;
-    static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata;
-    static final int ICON_G = R.drawable.ic_g_mobiledata;
-    static final int ICON_E = R.drawable.ic_e_mobiledata;
-    static final int ICON_H = R.drawable.ic_h_mobiledata;
-    static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
-    static final int ICON_3G = R.drawable.ic_3g_mobiledata;
-    static final int ICON_4G = R.drawable.ic_4g_mobiledata;
-    static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
-    static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
-    static final int ICON_1X = R.drawable.ic_1x_mobiledata;
-    static final int ICON_5G = R.drawable.ic_5g_mobiledata;
-    static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
+    public static final int ICON_LTE = R.drawable.ic_lte_mobiledata;
+    public static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata;
+    public static final int ICON_G = R.drawable.ic_g_mobiledata;
+    public static final int ICON_E = R.drawable.ic_e_mobiledata;
+    public static final int ICON_H = R.drawable.ic_h_mobiledata;
+    public static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
+    public static final int ICON_3G = R.drawable.ic_3g_mobiledata;
+    public static final int ICON_4G = R.drawable.ic_4g_mobiledata;
+    public static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+    public static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
+    public static final int ICON_1X = R.drawable.ic_1x_mobiledata;
+    public static final int ICON_5G = R.drawable.ic_5g_mobiledata;
+    public static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
 
-    static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
+    public static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
             "CARRIER_NETWORK_CHANGE",
             null,
             null,
@@ -53,7 +57,7 @@
             0,
             false);
 
-    static final MobileIconGroup THREE_G = new MobileIconGroup(
+    public static final MobileIconGroup THREE_G = new MobileIconGroup(
             "3G",
             null,
             null,
@@ -66,7 +70,7 @@
             TelephonyIcons.ICON_3G,
             true);
 
-    static final MobileIconGroup WFC = new MobileIconGroup(
+    public static final MobileIconGroup WFC = new MobileIconGroup(
             "WFC",
             null,
             null,
@@ -77,7 +81,7 @@
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             0, 0, false);
 
-    static final MobileIconGroup UNKNOWN = new MobileIconGroup(
+    public static final MobileIconGroup UNKNOWN = new MobileIconGroup(
             "Unknown",
             null,
             null,
@@ -88,7 +92,7 @@
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             0, 0, false);
 
-    static final MobileIconGroup E = new MobileIconGroup(
+    public static final MobileIconGroup E = new MobileIconGroup(
             "E",
             null,
             null,
@@ -101,7 +105,7 @@
             TelephonyIcons.ICON_E,
             false);
 
-    static final MobileIconGroup ONE_X = new MobileIconGroup(
+    public static final MobileIconGroup ONE_X = new MobileIconGroup(
             "1X",
             null,
             null,
@@ -114,7 +118,7 @@
             TelephonyIcons.ICON_1X,
             true);
 
-    static final MobileIconGroup G = new MobileIconGroup(
+    public static final MobileIconGroup G = new MobileIconGroup(
             "G",
             null,
             null,
@@ -127,7 +131,7 @@
             TelephonyIcons.ICON_G,
             false);
 
-    static final MobileIconGroup H = new MobileIconGroup(
+    public static final MobileIconGroup H = new MobileIconGroup(
             "H",
             null,
             null,
@@ -140,7 +144,7 @@
             TelephonyIcons.ICON_H,
             false);
 
-    static final MobileIconGroup H_PLUS = new MobileIconGroup(
+    public static final MobileIconGroup H_PLUS = new MobileIconGroup(
             "H+",
             null,
             null,
@@ -153,7 +157,7 @@
             TelephonyIcons.ICON_H_PLUS,
             false);
 
-    static final MobileIconGroup FOUR_G = new MobileIconGroup(
+    public static final MobileIconGroup FOUR_G = new MobileIconGroup(
             "4G",
             null,
             null,
@@ -166,12 +170,12 @@
             TelephonyIcons.ICON_4G,
             true);
 
-    static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
+    public static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
             "4G+",
             null,
             null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0,0,
+            0, 0,
             0,
             0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
@@ -179,7 +183,7 @@
             TelephonyIcons.ICON_4G_PLUS,
             true);
 
-    static final MobileIconGroup LTE = new MobileIconGroup(
+    public static final MobileIconGroup LTE = new MobileIconGroup(
             "LTE",
             null,
             null,
@@ -192,7 +196,7 @@
             TelephonyIcons.ICON_LTE,
             true);
 
-    static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
+    public static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
             "LTE+",
             null,
             null,
@@ -205,7 +209,7 @@
             TelephonyIcons.ICON_LTE_PLUS,
             true);
 
-    static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+    public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
             "5Ge",
             null,
             null,
@@ -218,7 +222,7 @@
             TelephonyIcons.ICON_5G_E,
             true);
 
-    static final MobileIconGroup NR_5G = new MobileIconGroup(
+    public static final MobileIconGroup NR_5G = new MobileIconGroup(
             "5G",
             null,
             null,
@@ -232,7 +236,7 @@
             TelephonyIcons.ICON_5G,
             true);
 
-    static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
+    public static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
             "5G_PLUS",
             null,
             null,
@@ -246,7 +250,7 @@
             TelephonyIcons.ICON_5G_PLUS,
             true);
 
-    static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+    public static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
             "DataDisabled",
             null,
             null,
@@ -259,7 +263,7 @@
             0,
             false);
 
-    static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
+    public static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
             "NotDefaultData",
             null,
             null,
@@ -276,7 +280,7 @@
     // in QSCarrier#hasValidTypeContentDescription
 
     /** Mapping icon name(lower case) to the icon object. */
-    static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON;
+    public static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON;
     static {
         ICON_NAME_TO_ICON = new HashMap<>();
         ICON_NAME_TO_ICON.put("carrier_network_change", CARRIER_NETWORK_CHANGE);
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5ad43e3..846efa7 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -180,7 +180,7 @@
     <!-- Default state of tap to wake -->
     <bool name="def_double_tap_to_wake">true</bool>
 
-    <!-- Default for Settings.Secure.NFC_PAYMENT_COMPONENT -->
+    <!-- Default for Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT -->
     <string name="def_nfc_payment_component"></string>
 
     <!-- Default setting for ability to add users from the lock screen -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index af775cc6..411a78a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -155,6 +155,7 @@
     <uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" />
     <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" />
     <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
+    <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.SET_TIME" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6e7b0b8..3fb5a9c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -391,7 +391,7 @@
         </activity-alias>
 
         <activity
-            android:name="com.android.wm.shell.splitscreen.ForcedResizableInfoActivity"
+            android:name="com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity"
             android:theme="@style/ForcedResizableTheme"
             android:excludeFromRecents="true"
             android:stateNotNeeded="true"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
index 53f7e44..bcd28a6 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
@@ -50,4 +50,6 @@
     public abstract void onStateChanged(State state);
 
     public abstract int getDetailY();
+
+    public void setShowLabels(boolean show) {}
 }
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index d1a1582..f215625 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -66,7 +66,6 @@
     <string name="kg_wrong_pin" msgid="4160978845968732624">"NIP incorrect"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
       <item quantity="one">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
-      <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dessinez votre schéma"</string>
@@ -90,13 +89,11 @@
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"NIP de carte SIM incorrect. Vous devez maintenant communiquer avec votre fournisseur de services pour déverrouiller votre appareil."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
       <item quantity="one">Le NIP de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
-      <item quantity="many">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Le NIP de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La carte SIM est inutilisable. Communiquez avec votre fournisseur de services."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
       <item quantity="one">Le code PUK de la carte SIM est incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable.</item>
-      <item quantity="many">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
       <item quantity="other">Le code PUK de la carte SIM est incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM devienne définitivement inutilisable.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Le déverrouillage par NIP de la carte SIM a échoué."</string>
@@ -118,29 +115,24 @@
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"L\'appareil a été verrouillé manuellement"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le schéma.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le schéma.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le NIP.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le NIP.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le mot de passe.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item>
     </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Doigt non reconnu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Doigt non reconnu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
       <item quantity="one">Entrez le NIP de votre carte SIM. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
-      <item quantity="many">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Entrez le NIP de votre carte SIM. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
       <item quantity="one">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item>
-      <item quantity="many">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
       <item quantity="other">La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM devienne définitivement inutilisable. Pour obtenir plus de détails, communiquez avec votre fournisseur de services.</item>
     </plurals>
     <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index ba35acd..3e52f50 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -66,7 +66,6 @@
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Code incorrect"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
       <item quantity="one">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
-      <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dessinez votre schéma"</string>
@@ -90,13 +89,11 @@
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Code PIN de la carte SIM incorrect. Vous devez désormais contacter votre opérateur pour déverrouiller votre appareil."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
       <item quantity="one">Code PIN de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative.</item>
-      <item quantity="many">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Code PIN de la carte SIM incorrect. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La carte SIM est inutilisable. Contactez votre opérateur."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
       <item quantity="one">Clé PUK de la carte SIM incorrecte. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable.</item>
-      <item quantity="many">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
       <item quantity="other">Clé PUK de la carte SIM incorrecte. Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Échec du déverrouillage à l\'aide du code PIN de la carte SIM."</string>
@@ -118,29 +115,24 @@
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Appareil verrouillé manuellement"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le schéma.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le schéma.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le code.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le code.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
       <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le mot de passe.</item>
-      <item quantity="many">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
       <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item>
     </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Non reconnu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non reconnu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
       <item quantity="one">Saisissez le code de la carte SIM. <xliff:g id="NUMBER_1">%d</xliff:g> tentative restante.</item>
-      <item quantity="many">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Saisissez le code de la carte SIM. <xliff:g id="NUMBER_1">%d</xliff:g> tentatives restantes.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
       <item quantity="one">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item>
-      <item quantity="many">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
       <item quantity="other">La carte SIM est maintenant désactivée. Saisissez le code PUK pour continuer. Il vous reste <xliff:g id="_NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne devienne définitivement inutilisable. Pour de plus amples informations, veuillez contacter votre opérateur.</item>
     </plurals>
     <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string>
diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml
index 753f56a..e013a4e 100644
--- a/packages/SystemUI/res/layout/feedback_info.xml
+++ b/packages/SystemUI/res/layout/feedback_info.xml
@@ -24,18 +24,18 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:orientation="vertical"
-        android:paddingStart="@*android:dimen/notification_content_margin_start"
-        android:paddingEnd="@*android:dimen/notification_content_margin_end"
-        android:background="?android:attr/colorBackground"
-        android:theme="@*android:style/Theme.DeviceDefault.Light">
+        android:paddingStart="@dimen/notification_shade_content_margin_horizontal"
+        android:paddingEnd="@dimen/notification_shade_content_margin_horizontal"
+        android:background="?android:attr/colorBackground">
 
     <!-- Package Info -->
     <LinearLayout
         android:id="@+id/header"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_guts_conversation_header_height"
+        android:layout_height="wrap_content"
         android:gravity="center_vertical"
         android:clipChildren="false"
+        android:paddingTop="@dimen/notification_guts_header_top_padding"
         android:clipToPadding="false">
         <ImageView
             android:id="@+id/pkg_icon"
@@ -49,7 +49,6 @@
             android:layout_weight="1"
             android:layout_width="0dp"
             android:orientation="vertical"
-
             android:layout_height="wrap_content"
             android:minHeight="@dimen/notification_guts_conversation_icon_size"
             android:layout_centerVertical="true"
@@ -63,10 +62,11 @@
                 android:orientation="horizontal">
                 <TextView
                     android:id="@+id/pkg_name"
-                    android:layout_width="wrap_content"
+                    android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    style="@style/TextAppearance.NotificationImportanceChannelGroup"
+                    style="@style/TextAppearance.NotificationImportanceApp"
                     android:ellipsize="end"
+                    android:textDirection="locale"
                     android:maxLines="1"/>
             </LinearLayout>
         </LinearLayout>
@@ -76,8 +76,7 @@
         android:id="@+id/prompt"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@*android:dimen/notification_header_padding_top"
-        style="@style/TextAppearance.NotificationInfo.Secondary" />
+        android:layout_marginTop="@*android:dimen/notification_header_padding_top" />
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 2bf41d2..3c58d16 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -39,5 +39,6 @@
         android:layout_height="match_parent"
         android:visibility="gone"
         android:pointerIcon="crosshair"/>
-    <include layout="@layout/global_screenshot_static"/>
+    <include layout="@layout/global_screenshot_static"
+             android:id="@+id/global_screenshot_static"/>
 </com.android.systemui.screenshot.ScreenshotView>
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
index f474830..085e955 100644
--- a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -82,16 +82,25 @@
                     android:ellipsize="end" />
             </LinearLayout>
         </LinearLayout>
-        <TextView
-            android:id="@+id/content"
-            android:paddingVertical="3dp"
-            android:paddingHorizontal="12dp"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+        <LinearLayout
             android:background="@drawable/people_space_content_background"
-            android:textSize="14sp"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:maxLines="2"
-            android:ellipsize="end" />
+            android:layout_height="match_parent">
+            <TextView
+                android:id="@+id/content"
+                android:paddingVertical="3dp"
+                android:paddingHorizontal="12dp"
+                android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+                android:textSize="14sp"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:maxLines="2"
+                android:ellipsize="end" />
+            <ImageView
+                android:id="@+id/image"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"/>
+        </LinearLayout>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0e8e315..9f5c98d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -330,7 +330,6 @@
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
     </plurals>
     <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g> : <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
@@ -406,7 +405,6 @@
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="one">%d appareil</item>
-      <item quantity="many">%d devices</item>
       <item quantity="other">%d appareils</item>
     </plurals>
     <string name="quick_settings_notifications_label" msgid="3379631363952582758">"Notifications"</string>
@@ -499,7 +497,6 @@
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite d\'utilisateurs atteinte"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
       <item quantity="one">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateur.</item>
-      <item quantity="many">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
       <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateurs.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur?"</string>
@@ -774,12 +771,10 @@
     <string name="snoozed_for_time" msgid="7586689374860469469">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
       <item quantity="one">%d heure</item>
-      <item quantity="many">%d hours</item>
       <item quantity="other">%d heures</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
       <item quantity="one">%d minute</item>
-      <item quantity="many">%d minutes</item>
       <item quantity="other">%d minutes</item>
     </plurals>
     <string name="battery_panel_title" msgid="5931157246673665963">"Utilisation de la pile"</string>
@@ -1021,7 +1016,6 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'application pour laquelle ajouter des commandes"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> commande ajoutée.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 28b9bbe..b482c24 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -330,7 +330,6 @@
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> autres"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
     </plurals>
     <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g> : <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
@@ -406,7 +405,6 @@
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="one">%d appareil</item>
-      <item quantity="many">%d devices</item>
       <item quantity="other">%d appareils</item>
     </plurals>
     <string name="quick_settings_notifications_label" msgid="3379631363952582758">"Notifications"</string>
@@ -499,7 +497,6 @@
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite nombre utilisateurs atteinte"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
       <item quantity="one">Vous pouvez ajouter <xliff:g id="COUNT">%d</xliff:g> profil utilisateur.</item>
-      <item quantity="many">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
       <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> profils utilisateur.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur ?"</string>
@@ -774,12 +771,10 @@
     <string name="snoozed_for_time" msgid="7586689374860469469">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
       <item quantity="one">%d heure</item>
-      <item quantity="many">%d hours</item>
       <item quantity="other">%d heures</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
       <item quantity="one">%d minute</item>
-      <item quantity="many">%d minutes</item>
       <item quantity="other">%d minutes</item>
     </plurals>
     <string name="battery_panel_title" msgid="5931157246673665963">"Utilisation batterie"</string>
@@ -1021,7 +1016,6 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'appli pour laquelle ajouter des commandes"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> commande ajoutée.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 6a96a50..1e5a67a 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -789,7 +789,7 @@
     <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Зүүн"</string>
     <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Баруун"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Гол хэсэг"</string>
-    <string name="keyboard_key_tab" msgid="4592772350906496730">"Чихтэй хуудас"</string>
+    <string name="keyboard_key_tab" msgid="4592772350906496730">"Таб"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Зай"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Оруулах"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Арилгах"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 61cc913..8203bf6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -570,9 +570,9 @@
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir as definições de VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Abrir credenciais fidedignas"</string>
-    <string name="monitoring_description_network_logging" msgid="577305979174002252">"O seu gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o gestor."</string>
+    <string name="monitoring_description_network_logging" msgid="577305979174002252">"O seu gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara mais informações, contacte o gestor."</string>
     <string name="monitoring_description_vpn" msgid="1685428000684586870">"Concedeu autorização a uma app para configurar uma ligação VPN.\n\nEsta app pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Sites."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu gestor tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara obter mais informações, contacte o gestor.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu gestor tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara mais informações, contacte o gestor.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerido pelos teus pais. Estes podem ver e gerir informações como as apps que utilizas, a tua localização e o tempo de utilização."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="monitoring_description_app" msgid="376868879287922929">"Está associado à app <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 2bf513c..101124e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -24,10 +24,6 @@
          certain GPU's and thus can be turned off with only minimal visual impact. -->
     <bool name="config_notifications_round_rect_clipping">true</bool>
 
-    <!-- Control whether status bar should distinguish HSPA data icon form UMTS
-    data icon on devices -->
-    <bool name="config_hspa_data_distinguishable">false</bool>
-
     <!-- Component to be used as the status bar service.  Must implement the IStatusBar
      interface.  This name is in the ComponentName flattened format (package/class)  -->
     <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
@@ -56,9 +52,6 @@
     <!-- Show phone (voice) signal strength instead of data in mobile RSSI. -->
     <bool name="config_showPhoneRSSIForData">false</bool>
 
-    <!-- When true, show 1/2G networks as 3G. -->
-    <bool name="config_showMin3G">false</bool>
-
     <!-- Show rotation lock toggle in System UI-->
     <bool name="config_showRotationLock">true</bool>
 
@@ -358,7 +351,7 @@
     <bool name="config_showNotificationGear">true</bool>
 
     <!-- Whether or not a background should be drawn behind a notification. -->
-    <bool name="config_drawNotificationBackground">true</bool>
+    <bool name="config_drawNotificationBackground">false</bool>
 
     <!-- Whether or the notifications can be shown and dismissed with a drag. -->
     <bool name="config_enableNotificationShadeDrag">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7989b7a..6fa4aa1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -450,28 +450,6 @@
     <!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_battery_unknown">Battery percentage unknown.</string>
 
-    <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_no_phone">No phone.</string>
-    <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_phone_one_bar">Phone one bar.</string>
-    <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_phone_two_bars">Phone two bars.</string>
-    <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_phone_three_bars">Phone three bars.</string>
-    <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_phone_signal_full">Phone signal full.</string>
-
-    <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_no_data">No data.</string>
-    <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_data_one_bar">Data one bar.</string>
-    <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_data_two_bars">Data two bars.</string>
-    <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_data_three_bars">Data three bars.</string>
-    <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_data_signal_full">Data signal full.</string>
-
     <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] -->
     <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
 
@@ -493,11 +471,6 @@
     <!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wimax_signal_full">WiMAX signal full.</string>
 
-    <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string>
-    <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_ethernet_connected">Ethernet connected.</string>
-
     <!-- Content description of an item with no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_no_signal">No signal.</string>
     <!-- Content description of an item with no signal and no connection for accessibility (not shown on the screen) [CHAR LIMIT=NONE] -->
@@ -522,54 +495,16 @@
     <!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_desc_connecting">Connecting.</string>
 
-    <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_gprs">GPRS</string>
-
     <!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] -->
     <string name="data_connection_hspa">HSPA</string>
 
-    <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_3g">3G</string>
-
-    <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_3_5g">H</string>
-
-    <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_3_5g_plus">H+</string>
-
-    <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
-    <string name="data_connection_4g">4G</string>
-
-    <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_4g_plus">4G+</string>
-
-    <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_lte">LTE</string>
-
-    <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_lte_plus">LTE+</string>
-
     <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
     <string name="data_connection_5ge" translatable="false">5Ge</string>
 
-    <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5ge_html" translate="false"> &lt;i>5G &lt;small>E&lt;/small>&lt;/i> </string>
-
-    <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g" translatable="false">5G</string>
-
-    <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_5g_plus" translatable="false">5G+</string>
-
-    <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_cdma">1X</string>
 
     <!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] -->
     <string name="data_connection_roaming">Roaming</string>
 
-    <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] -->
-    <string name="data_connection_edge">EDGE</string>
-
     <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_data_connection_wifi">Wi-Fi</string>
 
@@ -582,12 +517,6 @@
     <!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] -->
     <string name="accessibility_cell_data_on">Mobile Data On</string>
 
-    <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
-    <string name="cell_data_off_content_description">Mobile data off</string>
-
-    <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] -->
-    <string name="not_default_data_content_description">Not set to use data</string>
-
     <!-- Content description of the cell data being disabled but shortened. [CHAR LIMIT=20] -->
     <string name="cell_data_off">Off</string>
 
@@ -603,9 +532,6 @@
     <!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_no_sims">No SIM card.</string>
 
-    <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] -->
-    <string name="carrier_network_change_mode">Carrier network changing</string>
-
     <!-- Content description of button to open battery details icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_battery_details">Open battery details</string>
 
@@ -1876,6 +1802,18 @@
     <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary -->
     <string name="notification_channel_summary_automatic">Have the system determine if this notification should make sound or vibration</string>
 
+    <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (alerted) -->
+    <string name="notification_channel_summary_automatic_alerted">&lt;b>Status:&lt;/b> Promoted to Default</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (silenced) -->
+    <string name="notification_channel_summary_automatic_silenced">&lt;b>Status:&lt;/b> Demoted to Silent</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (promoted) -->
+    <string name="notification_channel_summary_automatic_promoted">&lt;b>Status:&lt;/b> Ranked Higher</string>
+
+    <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (demoted) -->
+    <string name="notification_channel_summary_automatic_demoted">&lt;b>Status:&lt;/b> Ranked Lower</string>
+
     <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
     <string name="notification_channel_summary_priority">Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen</string>
 
@@ -1922,11 +1860,13 @@
     <string name="notification_appops_ok">OK</string>
 
     <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
-    <string name="feedback_silenced">This notification was silenced by the system.</string>
+    <string name="feedback_alerted">This notification was automatically &lt;b>promoted to Default&lt;/b> by the system.</string>
     <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
-    <string name="feedback_promoted">This notification was promoted by the system.</string>
+    <string name="feedback_silenced">This notification was automatically &lt;b>demoted to Silent&lt;/b> by the system.</string>
     <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
-    <string name="feedback_demoted">This notification was demoted by the system.</string>
+    <string name="feedback_promoted">This notification was automatically &lt;b>ranked higher&lt;/b> in your shade.</string>
+    <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
+    <string name="feedback_demoted">This notification was automatically &lt;b>ranked lower&lt;/b> in your shade.</string>
     <!-- Notification Inline controls: prompts the user for feedback [CHAR_LIMIT=NONE] -->
     <string name="feedback_prompt">Was this correct?</string>
     <!-- Notification Inline controls: responds to user provided feedback [CHAR_LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
deleted file mode 100644
index c0f8cae..0000000
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ /dev/null
@@ -1,109 +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;
-
-import android.annotation.NonNull;
-import android.app.Notification;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.ArraySet;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.NotificationInteractionTracker;
-import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.util.time.SystemClock;
-
-import javax.inject.Inject;
-
-/**
- * Extends the lifetime of foreground notification services such that they show for at least
- * five seconds
- */
-public class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender {
-
-    private static final String TAG = "FGSLifetimeExtender";
-    @VisibleForTesting
-    static final int MIN_FGS_TIME_MS = 5000;
-
-    private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback;
-    private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>();
-    private Handler mHandler = new Handler(Looper.getMainLooper());
-    private final SystemClock mSystemClock;
-    private final NotificationInteractionTracker mInteractionTracker;
-
-    @Inject
-    public ForegroundServiceLifetimeExtender(
-            NotificationInteractionTracker interactionTracker,
-            SystemClock systemClock) {
-        mSystemClock = systemClock;
-        mInteractionTracker = interactionTracker;
-    }
-
-    @Override
-    public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) {
-        mNotificationSafeToRemoveCallback = callback;
-    }
-
-    @Override
-    public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
-        if ((entry.getSbn().getNotification().flags
-                & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
-            return false;
-        }
-
-        // Entry has triggered a HUN or some other interruption, therefore it has been seen and the
-        // interrupter might be retaining it anyway.
-        if (entry.hasInterrupted()) {
-            return false;
-        }
-
-        boolean hasInteracted = mInteractionTracker.hasUserInteractedWith(entry.getKey());
-        long aliveTime = mSystemClock.uptimeMillis() - entry.getCreationTime();
-        return aliveTime < MIN_FGS_TIME_MS && !hasInteracted;
-    }
-
-    @Override
-    public boolean shouldExtendLifetimeForPendingNotification(
-            @NonNull NotificationEntry entry) {
-        return shouldExtendLifetime(entry);
-    }
-
-    @Override
-    public void setShouldManageLifetime(
-            @NonNull NotificationEntry entry, boolean shouldManage) {
-        if (!shouldManage) {
-            mManagedEntries.remove(entry);
-            return;
-        }
-
-        mManagedEntries.add(entry);
-
-        Runnable r = () -> {
-            if (mManagedEntries.contains(entry)) {
-                mManagedEntries.remove(entry);
-                if (mNotificationSafeToRemoveCallback != null) {
-                    mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey());
-                }
-            }
-        };
-        long delayAmt = MIN_FGS_TIME_MS
-                - (mSystemClock.uptimeMillis() - entry.getCreationTime());
-        mHandler.postDelayed(r, delayAmt);
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index d6cb114..04e26d3 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -50,7 +50,6 @@
             ForegroundServiceController foregroundServiceController,
             NotificationEntryManager notificationEntryManager,
             NotifPipeline notifPipeline,
-            ForegroundServiceLifetimeExtender fgsLifetimeExtender,
             SystemClock systemClock) {
         mContext = context;
         mForegroundServiceController = foregroundServiceController;
@@ -78,7 +77,6 @@
                 removeNotification(entry.getSbn());
             }
         });
-        mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender);
 
         notifPipeline.addCollectionListener(new NotifCollectionListener() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 6b4e8bd..08262de 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -106,7 +106,7 @@
             // components that shouldn't be run in the test environment
             builder = prepareSysUIComponentBuilder(builder, mWMComponent)
                     .setPip(mWMComponent.getPip())
-                    .setSplitScreen(mWMComponent.getSplitScreen())
+                    .setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
                     .setOneHanded(mWMComponent.getOneHanded())
                     .setBubbles(mWMComponent.getBubbles())
                     .setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
@@ -117,7 +117,7 @@
             // is separating this logic into newly creating SystemUITestsFactory.
             builder = prepareSysUIComponentBuilder(builder, mWMComponent)
                     .setPip(Optional.ofNullable(null))
-                    .setSplitScreen(Optional.ofNullable(null))
+                    .setLegacySplitScreen(Optional.ofNullable(null))
                     .setOneHanded(Optional.ofNullable(null))
                     .setBubbles(Optional.ofNullable(null))
                     .setHideDisplayCutout(Optional.ofNullable(null))
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 275bfaa..f22fa32 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -82,7 +82,7 @@
 import com.android.systemui.theme.ThemeOverlayApplier;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -213,7 +213,7 @@
             BroadcastDispatcher broadcastDispatcher,
             CommandQueue commandQueue,
             Optional<Pip> pipOptional,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             Optional<Recents> recentsOptional,
             Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index f9f68e2..926062b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -30,7 +30,7 @@
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -59,7 +59,7 @@
         Builder setPip(Optional<Pip> p);
 
         @BindsInstance
-        Builder setSplitScreen(Optional<SplitScreen> s);
+        Builder setLegacySplitScreen(Optional<LegacySplitScreen> s);
 
         @BindsInstance
         Builder setAppPairs(Optional<AppPairs> s);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index ec8c7da..a1bde58 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -24,7 +24,7 @@
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -69,7 +69,7 @@
     Optional<Pip> getPip();
 
     @WMSingleton
-    Optional<SplitScreen> getSplitScreen();
+    Optional<LegacySplitScreen> getLegacySplitScreen();
 
     @WMSingleton
     Optional<AppPairs> getAppPairs();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index b6ca77b..f7a4aca 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -137,7 +137,7 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.PrintWriter;
 import java.util.List;
@@ -181,7 +181,7 @@
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final CommandQueue mCommandQueue;
     private final Optional<Pip> mPipOptional;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     private final Optional<Recents> mRecentsOptional;
     private final SystemActions mSystemActions;
     private final Handler mHandler;
@@ -409,7 +409,7 @@
             BroadcastDispatcher broadcastDispatcher,
             CommandQueue commandQueue,
             Optional<Pip> pipOptional,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
             NotificationRemoteInputManager notificationRemoteInputManager,
@@ -697,7 +697,7 @@
         }
 
         if (mStartingQuickSwitchRotation == -1 || mSplitScreenOptional
-                .map(SplitScreen::isDividerVisible).orElse(false)) {
+                .map(LegacySplitScreen::isDividerVisible).orElse(false)) {
             // Hide the secondary home handle if we are in multiwindow since apps in multiwindow
             // aren't allowed to set the display orientation
             resetSecondaryHandle();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index f7f3400..461ab3a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -65,7 +65,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -98,7 +98,7 @@
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final CommandQueue mCommandQueue;
     private final Optional<Pip> mPipOptional;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     private final Optional<Recents> mRecentsOptional;
     private final Lazy<StatusBar> mStatusBarLazy;
     private final ShadeController mShadeController;
@@ -133,7 +133,7 @@
             BroadcastDispatcher broadcastDispatcher,
             CommandQueue commandQueue,
             Optional<Pip> pipOptional,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             Optional<Recents> recentsOptional,
             Lazy<StatusBar> statusBarLazy,
             ShadeController shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 4c3ac40..d6f0799 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -93,7 +93,7 @@
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.PrintWriter;
 import java.util.function.Consumer;
@@ -1289,8 +1289,8 @@
         return super.onApplyWindowInsets(insets);
     }
 
-    void registerDockedListener(SplitScreen splitScreen) {
-        splitScreen.registerInSplitScreenListener(mDockedListener);
+    void registerDockedListener(LegacySplitScreen legacySplitScreen) {
+        legacySplitScreen.registerInSplitScreenListener(mDockedListener);
     }
 
     void registerPipExclusionBoundsChangeListener(Pip pip) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 6dee63c..c2c4ad8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -76,6 +76,7 @@
 import com.android.systemui.tracing.nano.SystemUiTraceProto;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -207,10 +208,15 @@
     private BackGestureTfClassifierProvider mBackGestureTfClassifierProvider;
     private Map<String, Integer> mVocab;
     private boolean mUseMLModel;
+    // minimum width below which we do not run the model
+    private int mMLEnableWidth;
     private float mMLModelThreshold;
     private String mPackageName;
     private float mMLResults;
 
+    private static final int MAX_LOGGED_PREDICTIONS = 10;
+    private ArrayDeque<String> mPredictionLog = new ArrayDeque<>();
+
     private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
 
     private final NavigationEdgeBackPlugin.BackCallback mBackCallback =
@@ -302,6 +308,11 @@
         mBottomGestureHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, gestureHeight,
                 dm);
 
+        // Set the minimum bounds to activate ML to 12dp or the minimum of configured values
+        mMLEnableWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12.0f, dm);
+        if (mMLEnableWidth > mEdgeWidthRight) mMLEnableWidth = mEdgeWidthRight;
+        if (mMLEnableWidth > mEdgeWidthLeft) mMLEnableWidth = mEdgeWidthLeft;
+
         // Reduce the default touch slop to ensure that we can intercept the gesture
         // before the app starts to react to it.
         // TODO(b/130352502) Tune this value and extract into a constant
@@ -494,6 +505,7 @@
     private void updateMLModelState() {
         boolean newState = mIsEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
                 SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
+
         if (newState == mUseMLModel) {
             return;
         }
@@ -519,11 +531,10 @@
         }
     }
 
-    private float getBackGesturePredictionsCategory(int x, int y) {
-        if (!mVocab.containsKey(mPackageName)) {
+    private int getBackGesturePredictionsCategory(int x, int y, int app) {
+        if (app == -1) {
             return -1;
         }
-
         int distanceFromEdge;
         int location;
         if (x <= mDisplaySize.x / 2.0) {
@@ -538,21 +549,19 @@
             new long[]{(long) mDisplaySize.x},
             new long[]{(long) distanceFromEdge},
             new long[]{(long) location},
-            new long[]{(long) mVocab.get(mPackageName)},
+            new long[]{(long) app},
             new long[]{(long) y},
         };
 
         mMLResults = mBackGestureTfClassifierProvider.predict(featuresVector);
-        if (mMLResults == -1) return -1;
-
+        if (mMLResults == -1) {
+            return -1;
+        }
         return mMLResults >= mMLModelThreshold ? 1 : 0;
     }
 
     private boolean isWithinTouchRegion(int x, int y) {
-        boolean withinRange = false;
-        float results = -1;
-
-         // Disallow if we are in the bottom gesture area
+        // Disallow if we are in the bottom gesture area
         if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
             return false;
         }
@@ -570,15 +579,33 @@
             return false;
         }
 
-        if (mUseMLModel &&  (results = getBackGesturePredictionsCategory(x, y)) != -1) {
-            withinRange = results == 1 ? true : false;
-        } else {
-            // Denotes whether we should proceed with the gesture.
-            // Even if it is false, we may want to log it assuming
-            // it is not invalid due to exclusion.
-            withinRange = x <= mEdgeWidthLeft + mLeftInset
-                    || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset);
+        int app = -1;
+        if (mVocab != null) {
+            app = mVocab.getOrDefault(mPackageName, -1);
         }
+        // Check if we are within the tightest bounds beyond which
+        // we would not need to run the ML model.
+        boolean withinRange = x <= mMLEnableWidth + mLeftInset
+                || x >= (mDisplaySize.x - mMLEnableWidth - mRightInset);
+        if (!withinRange) {
+            int results = -1;
+            if (mUseMLModel && (results = getBackGesturePredictionsCategory(x, y, app)) != -1) {
+                withinRange = results == 1;
+            } else {
+                // Denotes whether we should proceed with the gesture.
+                // Even if it is false, we may want to log it assuming
+                // it is not invalid due to exclusion.
+                withinRange = x <= mEdgeWidthLeft + mLeftInset
+                        || x >= (mDisplaySize.x - mEdgeWidthRight - mRightInset);
+            }
+        }
+
+        // For debugging purposes
+        if (mPredictionLog.size() >= MAX_LOGGED_PREDICTIONS) {
+            mPredictionLog.removeFirst();
+        }
+        mPredictionLog.addLast(String.format("[%d,%d,%d,%f,%d]",
+                x, y, app, mMLResults, withinRange ? 1 : 0));
 
         // Always allow if the user is in a transient sticky immersive state
         if (mIsNavBarShownTransiently) {
@@ -774,6 +801,8 @@
         pw.println("  mIsAttached=" + mIsAttached);
         pw.println("  mEdgeWidthLeft=" + mEdgeWidthLeft);
         pw.println("  mEdgeWidthRight=" + mEdgeWidthRight);
+        pw.println("  mIsNavBarShownTransiently=" + mIsNavBarShownTransiently);
+        pw.println("  mPredictionLog=" + String.join(";", mPredictionLog));
     }
 
     private boolean isGestureBlockingActivityRunning() {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 4a633c3..e43eb9f 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -136,8 +136,12 @@
         editor.putString(String.valueOf(mAppWidgetId), tile.getId());
         editor.commit();
         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
+        Bundle options = new Bundle();
+        options.putParcelable(PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE, tile);
+        appWidgetManager.updateAppWidgetOptions(mAppWidgetId, options);
         int[] widgetIds = appWidgetManager.getAppWidgetIds(
                 new ComponentName(mContext, PeopleSpaceWidgetProvider.class));
+        // TODO: Populate new widget with existing conversation notification, if there is any.
         PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds, mAppWidgetManager,
                 mNotificationManager);
         finishActivity();
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index bc9500a..d682379 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -16,7 +16,10 @@
 
 package com.android.systemui.people;
 
+import static android.app.Notification.EXTRA_MESSAGES;
+
 import android.app.INotificationManager;
+import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.people.ConversationChannel;
 import android.app.people.IPeopleManager;
@@ -26,7 +29,6 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.LauncherApps;
-import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
@@ -34,20 +36,28 @@
 import android.icu.text.MeasureFormat;
 import android.icu.util.Measure;
 import android.icu.util.MeasureUnit;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.StatusBarNotification;
 import android.util.Log;
+import android.view.View;
 import android.widget.RemoteViews;
 
-import androidx.preference.PreferenceManager;
-
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.systemui.R;
 import com.android.systemui.people.widget.LaunchConversationActivity;
 import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 
 import java.time.Duration;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -63,6 +73,13 @@
     private static final int DAYS_IN_A_WEEK = 7;
     private static final int MIN_HOUR = 1;
     private static final int ONE_DAY = 1;
+    public static final String OPTIONS_PEOPLE_SPACE_TILE = "options_people_space_tile";
+
+    /** Represents whether {@link StatusBarNotification} was posted or removed. */
+    public enum NotificationAction {
+        POSTED,
+        REMOVED
+    }
 
     /** Returns a list of map entries corresponding to user's conversations. */
     public static List<Map.Entry<Long, PeopleSpaceTile>> getTiles(
@@ -93,75 +110,42 @@
     /** Updates {@code appWidgetIds} with their associated conversation stored. */
     public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds,
             AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
-        PackageManager mPackageManager = context.getPackageManager();
-        IPeopleManager mPeopleManager = IPeopleManager.Stub.asInterface(
+        IPeopleManager peopleManager = IPeopleManager.Stub.asInterface(
                 ServiceManager.getService(Context.PEOPLE_SERVICE));
-        LauncherApps mLauncherApps = context.getSystemService(LauncherApps.class);
+        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
-        activityIntent.addFlags(
-                Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_CLEAR_TASK
-                        | Intent.FLAG_ACTIVITY_NO_HISTORY
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         try {
-            List<Map.Entry<Long, PeopleSpaceTile>> shortcutInfos =
-                    PeopleSpaceUtils.getTiles(
-                            context, notificationManager,
-                            mPeopleManager, mLauncherApps);
+            List<Map.Entry<Long, PeopleSpaceTile>> tiles =
+                    PeopleSpaceUtils.getTiles(context, notificationManager,
+                            peopleManager, launcherApps);
+
             for (int appWidgetId : appWidgetIds) {
                 String shortcutId = sp.getString(String.valueOf(appWidgetId), null);
                 if (DEBUG) {
                     Log.d(TAG, "Set widget: " + appWidgetId + " with shortcut ID: " + shortcutId);
                 }
-
-                Optional<Map.Entry<Long, PeopleSpaceTile>> entry = shortcutInfos.stream().filter(
+                Optional<Map.Entry<Long, PeopleSpaceTile>> entry = tiles.stream().filter(
                         e -> e.getValue().getId().equals(shortcutId)).findFirst();
                 if (!entry.isPresent() || shortcutId == null) {
                     if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
                     //TODO: Delete app widget id when crash is fixed (b/175486868)
                     continue;
                 }
-                PeopleSpaceTile tile = entry.get().getValue();
-                RemoteViews views = new RemoteViews(context.getPackageName(),
-                        getLayout(tile));
+                PeopleSpaceTile tile =
+                        augmentTileFromStorage(entry.get().getValue(), appWidgetManager,
+                                appWidgetId);
 
-                String status = PeopleSpaceUtils.getLastInteractionString(context,
-                        entry.get().getKey());
-                views.setTextViewText(R.id.status, status);
-                views.setTextViewText(R.id.name, tile.getUserName().toString());
+                RemoteViews views = createRemoteViews(context, tile, entry.get().getKey(),
+                        appWidgetId);
 
-                activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
-                activityIntent.putExtra(
-                        PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
-                activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
-                views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
-                        context,
-                        appWidgetId,
-                        activityIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
-
-                views.setImageViewBitmap(
-                        R.id.package_icon,
-                        PeopleSpaceUtils.convertDrawableToBitmap(
-                                mPackageManager.getApplicationIcon(tile.getPackageName())
-                        )
-                );
-                views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
                 // Tell the AppWidgetManager to perform an update on the current app widget.
                 appWidgetManager.updateAppWidget(appWidgetId, views);
             }
         } catch (Exception e) {
-            Log.e(TAG, "Failed to retrieve conversations to set tiles");
+            Log.e(TAG, "Exception updating single conversation widgets: " + e);
         }
     }
 
-    /** Returns the layout ID for the {@code tile}. */
-    private static int getLayout(PeopleSpaceTile tile) {
-        return tile.getNotification() == null ? R.layout.people_space_large_avatar_tile :
-                R.layout.people_space_small_avatar_tile;
-    }
-
     /** Returns a list sorted by ascending last interaction time from {@code stream}. */
     private static List<Map.Entry<Long, PeopleSpaceTile>> getSortedTiles(
             IPeopleManager peopleManager, Stream<PeopleSpaceTile> stream) {
@@ -172,6 +156,152 @@
                 .collect(Collectors.toList());
     }
 
+    /** Augment {@link PeopleSpaceTile} with fields from stored tile. */
+    @VisibleForTesting
+    static PeopleSpaceTile augmentTileFromStorage(PeopleSpaceTile tile,
+            AppWidgetManager appWidgetManager, int appWidgetId) {
+        Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+        PeopleSpaceTile storedTile = options.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+        if (storedTile == null) {
+            return tile;
+        }
+        return tile.toBuilder()
+                .setNotificationKey(storedTile.getNotificationKey())
+                .setNotificationContent(storedTile.getNotificationContent())
+                .setNotificationDataUri(storedTile.getNotificationDataUri())
+                .build();
+    }
+
+    /** If incoming notification changed tile, store the changes in the tile options. */
+    public static void storeNotificationChange(StatusBarNotification sbn,
+            NotificationAction notificationAction, AppWidgetManager appWidgetManager,
+            int appWidgetId) {
+        Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
+        PeopleSpaceTile storedTile = options.getParcelable(OPTIONS_PEOPLE_SPACE_TILE);
+        if (notificationAction == PeopleSpaceUtils.NotificationAction.POSTED) {
+            if (DEBUG) Log.i(TAG, "Adding notification to storage, appWidgetId: " + appWidgetId);
+            Notification.MessagingStyle.Message message = getLastMessagingStyleMessage(sbn);
+            if (message == null) {
+                if (DEBUG) Log.i(TAG, "Notification doesn't have content, skipping.");
+                return;
+            }
+            storedTile = storedTile
+                    .toBuilder()
+                    .setNotificationKey(sbn.getKey())
+                    .setNotificationContent(message.getText())
+                    .setNotificationDataUri(message.getDataUri())
+                    .build();
+        } else {
+            if (DEBUG) {
+                Log.i(TAG, "Removing notification from storage, appWidgetId: " + appWidgetId);
+            }
+            storedTile = storedTile
+                    .toBuilder()
+                    .setNotificationKey(null)
+                    .setNotificationContent(null)
+                    .setNotificationDataUri(null)
+                    .build();
+        }
+        Bundle newOptions = new Bundle();
+        newOptions.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, storedTile);
+        appWidgetManager.updateAppWidgetOptions(appWidgetId, newOptions);
+    }
+
+    private static RemoteViews createRemoteViews(Context context, PeopleSpaceTile tile,
+            long lastInteraction, int appWidgetId) throws Exception {
+        // TODO: If key is null or if text and data uri are null.
+        if (tile.getNotificationKey() == null) {
+            return createLastInteractionRemoteViews(context, tile, lastInteraction, appWidgetId);
+        }
+        return createNotificationRemoteViews(context, tile, lastInteraction, appWidgetId);
+    }
+
+    private static RemoteViews createLastInteractionRemoteViews(Context context,
+            PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
+            throws Exception {
+        RemoteViews views = new RemoteViews(
+                    context.getPackageName(), R.layout.people_space_large_avatar_tile);
+        String status = PeopleSpaceUtils.getLastInteractionString(
+                context, lastInteraction);
+        views.setTextViewText(R.id.status, status);
+
+        views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+        return views;
+    }
+
+    private static RemoteViews createNotificationRemoteViews(Context context,
+            PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
+            throws Exception {
+
+        RemoteViews views = new RemoteViews(
+                context.getPackageName(), R.layout.people_space_small_avatar_tile);
+        Uri image = tile.getNotificationDataUri();
+        if (image != null) {
+            //TODO: Use NotificationInlineImageCache
+            views.setImageViewUri(R.id.image, image);
+            views.setViewVisibility(R.id.image, View.VISIBLE);
+            views.setViewVisibility(R.id.content, View.GONE);
+        } else {
+            views.setTextViewText(R.id.content, tile.getNotificationContent());
+            views.setViewVisibility(R.id.content, View.VISIBLE);
+            views.setViewVisibility(R.id.image, View.GONE);
+        }
+
+        views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+        return views;
+    }
+
+    private static RemoteViews setCommonRemoteViewsFields(
+            Context context, RemoteViews views, PeopleSpaceTile tile, int appWidgetId)
+            throws Exception {
+        views.setTextViewText(R.id.name, tile.getUserName().toString());
+        views.setImageViewBitmap(
+                R.id.package_icon,
+                PeopleSpaceUtils.convertDrawableToBitmap(
+                        context.getPackageManager().getApplicationIcon(tile.getPackageName())
+                )
+        );
+        views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
+
+        Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
+        activityIntent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                        | Intent.FLAG_ACTIVITY_NO_HISTORY
+                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
+        activityIntent.putExtra(
+                PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
+        activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+        views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
+                context,
+                appWidgetId,
+                activityIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
+        return views;
+    }
+
+    /** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
+    public static Notification.MessagingStyle.Message getLastMessagingStyleMessage(
+            StatusBarNotification sbn) {
+        Notification notification = sbn.getNotification();
+        if (notification == null) {
+            return null;
+        }
+        if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle())
+                && notification.extras != null) {
+            final Parcelable[] messages = notification.extras.getParcelableArray(EXTRA_MESSAGES);
+            if (!ArrayUtils.isEmpty(messages)) {
+                List<Notification.MessagingStyle.Message> sortedMessages =
+                        Notification.MessagingStyle.Message.getMessagesFromBundleArray(messages);
+                sortedMessages.sort(Collections.reverseOrder(
+                        Comparator.comparing(Notification.MessagingStyle.Message::getTimestamp)));
+                return sortedMessages.get(0);
+            }
+        }
+        return null;
+    }
+
     /** Returns the last interaction time with the user specified by {@code PeopleSpaceTile}. */
     private static Long getLastInteraction(IPeopleManager peopleManager,
             PeopleSpaceTile tile) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index ac32e19..ad6046b 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -21,8 +21,10 @@
 import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
@@ -35,6 +37,8 @@
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
 
+import java.util.Objects;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
@@ -84,7 +88,6 @@
             int[] widgetIds = mAppWidgetService.getAppWidgetIds(
                     new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
             );
-
             if (widgetIds.length == 0) {
                 if (DEBUG) Log.d(TAG, "no widgets to update");
                 return;
@@ -93,6 +96,7 @@
             if (DEBUG) Log.d(TAG, "updating " + widgetIds.length + " widgets");
             boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+
             if (showSingleConversation) {
                 PeopleSpaceUtils.updateSingleConversationWidgets(mContext, widgetIds,
                         mAppWidgetManager, mNotificationManager);
@@ -107,6 +111,41 @@
     }
 
     /**
+     * Check if any existing People tiles match the incoming notification change, and store the
+     * change in the tile if so.
+     */
+    public void storeNotificationChange(StatusBarNotification sbn,
+            PeopleSpaceUtils.NotificationAction notificationAction) {
+        if (DEBUG) Log.d(TAG, "storeNotificationChange called");
+        boolean showSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+        if (!showSingleConversation) {
+            return;
+        }
+        try {
+            int[] widgetIds = mAppWidgetService.getAppWidgetIds(
+                    new ComponentName(mContext, PeopleSpaceWidgetProvider.class)
+            );
+            if (widgetIds.length == 0) {
+                return;
+            }
+
+            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+            for (int widgetId : widgetIds) {
+                String shortcutId = sp.getString(String.valueOf(widgetId), null);
+                if (!Objects.equals(sbn.getShortcutId(), shortcutId)) {
+                    continue;
+                }
+                if (DEBUG) Log.d(TAG, "Storing notification change, key:" + sbn.getKey());
+                PeopleSpaceUtils.storeNotificationChange(
+                        sbn, notificationAction, mAppWidgetManager, widgetId);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Exception: " + e);
+        }
+    }
+
+    /**
      * Attaches the manager to the pipeline, making it ready to receive events. Should only be
      * called once.
      */
@@ -120,6 +159,7 @@
         public void onNotificationPosted(
                 StatusBarNotification sbn, NotificationListenerService.RankingMap rankingMap) {
             if (DEBUG) Log.d(TAG, "onNotificationPosted");
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.POSTED);
             updateWidgets();
         }
 
@@ -129,6 +169,7 @@
                 NotificationListenerService.RankingMap rankingMap
         ) {
             if (DEBUG) Log.d(TAG, "onNotificationRemoved");
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
             updateWidgets();
         }
 
@@ -138,6 +179,7 @@
                 NotificationListenerService.RankingMap rankingMap,
                 int reason) {
             if (DEBUG) Log.d(TAG, "onNotificationRemoved with reason " + reason);
+            storeNotificationChange(sbn, PeopleSpaceUtils.NotificationAction.REMOVED);
             updateWidgets();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index addbd5f..321f732 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -70,6 +70,8 @@
     private int mMinRows = 1;
     private int mMaxColumns = TileLayout.NO_MAX_COLUMNS;
 
+    private boolean mShowLabels = true;
+
     public PagedTileLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         mScroller = new Scroller(context, SCROLL_CUBIC);
@@ -82,6 +84,16 @@
     }
     private int mLastMaxHeight = -1;
 
+    @Override
+    public void setShowLabels(boolean show) {
+        mShowLabels = show;
+        for (TilePage p : mPages) {
+            p.setShowLabels(show);
+        }
+        mDistributeTiles = true;
+        requestLayout();
+    }
+
     public void saveInstanceState(Bundle outState) {
         outState.putInt(CURRENT_PAGE, getCurrentItem());
     }
@@ -219,6 +231,7 @@
                 .inflate(R.layout.qs_paged_page, this, false);
         page.setMinRows(mMinRows);
         page.setMaxColumns(mMaxColumns);
+        page.setShowLabels(mShowLabels);
         return page;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 87a8da0..65f174c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -829,6 +829,8 @@
         default void setExpansion(float expansion) {}
 
         int getNumVisibleTiles();
+
+        default void setShowLabels(boolean show) {}
     }
 
     interface OnConfigurationChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 8ee284b..d58895e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -52,6 +52,8 @@
  */
 @QSScope
 public class QSPanelController extends QSPanelControllerBase<QSPanel> {
+    public static final String QS_REMOVE_LABELS = "sysui_remove_labels";
+
     private final QSSecurityFooter mQsSecurityFooter;
     private final TunerService mTunerService;
     private final QSCustomizerController mQsCustomizerController;
@@ -120,6 +122,7 @@
         updateMediaDisappearParameters();
 
         mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
+        mTunerService.addTunable(mTunable, QS_REMOVE_LABELS);
         mView.updateResources();
         if (mView.isListening()) {
             refreshAllTiles();
@@ -133,6 +136,13 @@
     }
 
     @Override
+    boolean switchTileLayout(boolean force) {
+        boolean result = super.switchTileLayout(force);
+        getTileLayout().setShowLabels(mShowLabels);
+        return result;
+    }
+
+    @Override
     protected QSTileRevealController createTileRevealController() {
         return mQsTileRevealControllerFactory.create(
                 this, (PagedTileLayout) mView.createRegularTileLayout());
@@ -140,6 +150,7 @@
 
     @Override
     protected void onViewDetached() {
+        mTunerService.removeTunable(mTunable);
         mTunerService.removeTunable(mView);
         mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
         if (mBrightnessMirrorController != null) {
@@ -305,5 +316,21 @@
     public boolean isExpanded() {
         return mView.isExpanded();
     }
+
+    private TunerService.Tunable mTunable = new TunerService.Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            if (QS_REMOVE_LABELS.equals(key)) {
+                boolean newShowLabels = "0".equals(newValue);
+                if (mShowLabels == newShowLabels) return;
+                mShowLabels = newShowLabels;
+                for (TileRecord t : mRecords) {
+                    t.tileView.setShowLabels(mShowLabels);
+                }
+                getTileLayout().setShowLabels(mShowLabels);
+                mView.requestLayout();
+            }
+        }
+    };
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 4418a74..5282f08 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -71,6 +71,7 @@
     private float mRevealExpansion;
 
     private final QSHost.Callback mQSHostCallback = this::setTiles;
+    protected boolean mShowLabels = true;
 
     private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
             new QSPanel.OnConfigurationChangedListener() {
@@ -183,6 +184,7 @@
         final TileRecord r = new TileRecord();
         r.tile = tile;
         r.tileView = mHost.createTileView(tile, collapsedView);
+        r.tileView.setShowLabels(mShowLabels);
         mView.addTile(r);
         mRecords.add(r);
         mCachedSpecs = getTilesSpecs();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 348dca5..e38c931 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -26,6 +26,7 @@
     protected int mColumns;
     protected int mCellWidth;
     protected int mCellHeight;
+    protected int mMaxCellHeight;
     protected int mCellMarginHorizontal;
     protected int mCellMarginVertical;
     protected int mSidePadding;
@@ -35,6 +36,7 @@
     private int mCellMarginTop;
     protected boolean mListening;
     protected int mMaxAllowedRows = 3;
+    private boolean mShowLabels;
 
     // Prototyping with less rows
     private final boolean mLessRows;
@@ -49,10 +51,17 @@
     public TileLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         setFocusableInTouchMode(true);
-        mLessRows = (Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)
-                || useQsMediaPlayer(context);
+        mShowLabels = Settings.Secure.getInt(context.getContentResolver(),
+                QSPanelController.QS_REMOVE_LABELS, 0) == 0;
+        mLessRows = ((Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)
+                || useQsMediaPlayer(context));
         updateResources();
+    }
 
+    @Override
+    public void setShowLabels(boolean show) {
+        mShowLabels = show;
+        updateResources();
     }
 
     @Override
@@ -117,12 +126,15 @@
     public boolean updateResources() {
         final Resources res = mContext.getResources();
         mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
-        mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
+        mMaxCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
         mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
         mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
+        if (!mShowLabels && mCellMarginVertical == 0) {
+            mCellMarginVertical = mCellMarginHorizontal;
+        }
         mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
         mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
-        if (mLessRows) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
+        if (mLessRows && mShowLabels) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
         if (updateColumns()) {
             requestLayout();
             return true;
@@ -153,10 +165,12 @@
 
         // Measure each QS tile.
         View previousView = this;
+        int verticalMeasure = exactly(getCellHeight());
         for (TileRecord record : mRecords) {
             if (record.tileView.getVisibility() == GONE) continue;
-            record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
+            record.tileView.measure(exactly(mCellWidth), verticalMeasure);
             previousView = record.tileView.updateAccessibilityOrder(previousView);
+            mCellHeight = record.tileView.getMeasuredHeight();
         }
 
         // Only include the top margin in our measurement if we have more than 1 row to show.
@@ -180,9 +194,10 @@
                 // Add the cell margin in order to divide easily by the height + the margin below
                 + mCellMarginVertical;
         final int previousRows = mRows;
-        mRows = availableHeight / (mCellHeight + mCellMarginVertical);
-        if (mRows < mMinRows) {
-            mRows = mMinRows;
+        mRows = availableHeight / (getCellHeight() + mCellMarginVertical);
+        final int minRows = mShowLabels ? mMinRows : mMinRows + 1;
+        if (mRows < minRows) {
+            mRows = minRows;
         } else if (mRows >= mMaxAllowedRows) {
             mRows = mMaxAllowedRows;
         }
@@ -201,6 +216,9 @@
         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
     }
 
+    private int getCellHeight() {
+        return mShowLabels ? mMaxCellHeight : mMaxCellHeight / 2;
+    }
 
     protected void layoutTileRecords(int numRecords) {
         final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index ad275f1..39b92dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -116,9 +116,11 @@
         return TextUtils.equals(typeContentDescription,
                 mContext.getString(R.string.data_connection_no_internet))
                 || TextUtils.equals(typeContentDescription,
-                mContext.getString(R.string.cell_data_off_content_description))
+                mContext.getString(
+                        com.android.settingslib.R.string.cell_data_off_content_description))
                 || TextUtils.equals(typeContentDescription,
-                mContext.getString(R.string.not_default_data_content_description));
+                mContext.getString(
+                        com.android.settingslib.R.string.not_default_data_content_description));
     }
 
     public void setCarrierText(CharSequence text) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index dce081f2..d7933d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Build;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
@@ -47,6 +48,7 @@
 public class QSCustomizer extends LinearLayout {
 
     static final int MENU_RESET = Menu.FIRST;
+    static final int MENU_REMOVE_LABELS = Menu.FIRST + 1;
     static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
 
     private final QSDetailClipper mClipper;
@@ -75,6 +77,11 @@
 
         toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
                 mContext.getString(com.android.internal.R.string.reset));
+        if (Build.IS_ENG || Build.IS_USERDEBUG) {
+            // Prototype menu item
+            toolbar.getMenu().add(Menu.NONE, MENU_REMOVE_LABELS, Menu.NONE, "Remove labels")
+                    .setCheckable(true);
+        }
         toolbar.setTitle(R.string.qs_edit);
         mRecyclerView = findViewById(android.R.id.list);
         mTransparentView = findViewById(R.id.customizer_transparent_view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 7ba51e5..9bf3b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.customize;
 
 import static com.android.systemui.qs.customize.QSCustomizer.EXTRA_QS_CUSTOMIZING;
+import static com.android.systemui.qs.customize.QSCustomizer.MENU_REMOVE_LABELS;
 import static com.android.systemui.qs.customize.QSCustomizer.MENU_RESET;
 
 import android.content.res.Configuration;
@@ -36,6 +37,7 @@
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSEditEvent;
 import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.dagger.QSScope;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -43,6 +45,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.ViewController;
 
 import java.util.ArrayList;
@@ -62,6 +65,7 @@
     private final ConfigurationController mConfigurationController;
     private final UiEventLogger mUiEventLogger;
     private final Toolbar mToolbar;
+    private final TunerService mTunerService;
 
     private final OnMenuItemClickListener mOnMenuItemClickListener = new OnMenuItemClickListener() {
         @Override
@@ -69,6 +73,11 @@
             if (item.getItemId() == MENU_RESET) {
                 mUiEventLogger.log(QSEditEvent.QS_EDIT_RESET);
                 reset();
+            } else if (item.getItemId() == MENU_REMOVE_LABELS) {
+                item.setChecked(!item.isChecked());
+                mTunerService.setValue(
+                        QSPanelController.QS_REMOVE_LABELS, item.isChecked() ? "1" : "0");
+                return false;
             }
             return false;
         }
@@ -93,11 +102,19 @@
         }
     };
 
+    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            mToolbar.getMenu().findItem(MENU_REMOVE_LABELS).setChecked(!("0".equals(newValue)));
+        }
+    };
+
     @Inject
     protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
             QSTileHost qsTileHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
             KeyguardStateController keyguardStateController, LightBarController lightBarController,
-            ConfigurationController configurationController, UiEventLogger uiEventLogger) {
+            ConfigurationController configurationController, UiEventLogger uiEventLogger,
+            TunerService tunerService) {
         super(view);
         mTileQueryHelper = tileQueryHelper;
         mQsTileHost = qsTileHost;
@@ -109,11 +126,14 @@
         mUiEventLogger = uiEventLogger;
 
         mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);
+
+        mTunerService = tunerService;
     }
 
     @Override
     protected void onViewAttached() {
         mView.updateNavBackDrop(getResources().getConfiguration(), mLightBarController);
+        mTunerService.addTunable(mTunable, QSPanelController.QS_REMOVE_LABELS);
 
         mConfigurationController.addCallback(mConfigurationListener);
 
@@ -143,6 +163,7 @@
 
     @Override
     protected void onViewDetached() {
+        mTunerService.removeTunable(mTunable);
         mTileQueryHelper.setListener(null);
         mToolbar.setOnMenuItemClickListener(null);
         mConfigurationController.removeCallback(mConfigurationListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index ef501c8..655e4e2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -56,7 +56,7 @@
 
     private static final String TAG = "QSTileBaseView";
     private static final int ICON_MASK_ID = com.android.internal.R.string.config_icon_mask;
-    private final H mHandler = new H();
+    protected final Handler mHandler = new H();
     private final int[] mLocInScreen = new int[2];
     private final FrameLayout mIconFrame;
     protected QSIconView mIcon;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 8a360ee..6502066 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -43,7 +43,7 @@
     protected TextView mSecondLine;
     private ImageView mPadLock;
     private int mState;
-    private ViewGroup mLabelContainer;
+    protected ViewGroup mLabelContainer;
     private View mExpandIndicator;
     private View mExpandSpace;
     private ColorStateList mColorLabelDefault;
@@ -151,4 +151,9 @@
         mLabelContainer.setClickable(false);
         mLabelContainer.setLongClickable(false);
     }
+
+    @Override
+    public void setShowLabels(boolean show) {
+        mHandler.post(() -> mLabelContainer.setVisibility(show ? VISIBLE : GONE));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index c27b047..6d9d587 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -95,7 +95,7 @@
 import com.android.wm.shell.onehanded.OneHandedEvents;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.pip.PipAnimationController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -130,7 +130,7 @@
     private final Context mContext;
     private final Optional<Pip> mPipOptional;
     private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     private SysUiState mSysUiState;
     private final Handler mHandler;
     private final Lazy<NavigationBarController> mNavBarControllerLazy;
@@ -636,7 +636,7 @@
             NavigationModeController navModeController,
             NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
             Optional<Pip> pipOptional,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             Optional<Lazy<StatusBar>> statusBarOptionalLazy,
             Optional<OneHanded> oneHandedOptional,
             BroadcastDispatcher broadcastDispatcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 6a4e93b..3f163d3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -84,6 +84,7 @@
  */
 public class ScreenshotController {
     private static final String TAG = logTag(ScreenshotController.class);
+
     /**
      * POD used in the AsyncTask which saves an image in the background.
      */
@@ -350,10 +351,20 @@
         // Inflate the screenshot layout
         mScreenshotView = (ScreenshotView)
                 LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
-        mScreenshotView.init(mUiEventLogger, this::resetScreenshotView);
+        mScreenshotView.init(mUiEventLogger, new ScreenshotView.ScreenshotViewCallback() {
+            @Override
+            public void onUserInteraction() {
+                resetTimeout();
+            }
+
+            @Override
+            public void onDismiss() {
+                resetScreenshotView();
+            }
+        });
 
         // TODO(159460485): Remove this when focus is handled properly in the system
-        mScreenshotView.setOnTouchListener((v, event) -> {
+        mDecorView.setOnTouchListener((v, event) -> {
             if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
                 if (DEBUG_INPUT) {
                     Log.d(TAG, "onTouch: ACTION_OUTSIDE");
@@ -432,7 +443,7 @@
             }
             if (DEBUG_WINDOW) {
                 Log.d(TAG, "saveScreenshot: screenshotView is already attached, resetting. "
-                        + "(dismissing=" + mScreenshotView.isDismissing()  + ")");
+                        + "(dismissing=" + mScreenshotView.isDismissing() + ")");
             }
             mScreenshotView.reset();
         }
@@ -580,11 +591,8 @@
         mSaveInBgTask.execute();
     }
 
-    /**
-     * Sets up the action shade and its entrance animation, once we get the screenshot URI.
-     */
-    private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
-        logSuccessOnActionsReady(imageData);
+    private void resetTimeout() {
+        mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
 
         AccessibilityManager accessibilityManager = (AccessibilityManager)
                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -592,12 +600,25 @@
                 SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS,
                 AccessibilityManager.FLAG_CONTENT_CONTROLS);
 
-        if (DEBUG_UI) {
-            Log.d(TAG, "Showing UI actions, dismiss timeout: " + timeoutMs + " ms");
-        }
         mScreenshotHandler.sendMessageDelayed(
                 mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
                 timeoutMs);
+        if (DEBUG_UI) {
+            Log.d(TAG, "dismiss timeout: " + timeoutMs + " ms");
+        }
+
+    }
+
+    /**
+     * Sets up the action shade and its entrance animation, once we get the screenshot URI.
+     */
+    private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
+        logSuccessOnActionsReady(imageData);
+        if (DEBUG_UI) {
+            Log.d(TAG, "Showing UI actions");
+        }
+
+        resetTimeout();
 
         if (imageData.uri != null) {
             mScreenshotHandler.post(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index cce60f9..4ca3dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -58,6 +58,7 @@
 import android.view.GestureDetector;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
+import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
@@ -83,6 +84,12 @@
 public class ScreenshotView extends FrameLayout implements
         ViewTreeObserver.OnComputeInternalInsetsListener {
 
+    interface ScreenshotViewCallback {
+        void onUserInteraction();
+
+        void onDismiss();
+    }
+
     private static final String TAG = logTag(ScreenshotView.class);
 
     private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
@@ -99,6 +106,7 @@
     private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
     private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
     private static final float ROUNDED_CORNER_RADIUS = .05f;
+    private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
 
     private final Interpolator mAccelerateInterpolator = new AccelerateInterpolator();
 
@@ -115,6 +123,7 @@
     private boolean mDirectionLTR;
 
     private ScreenshotSelectorView mScreenshotSelectorView;
+    private View mScreenshotStatic;
     private ImageView mScreenshotPreview;
     private ImageView mScreenshotFlash;
     private ImageView mActionsContainerBackground;
@@ -127,7 +136,7 @@
     private ScreenshotActionChip mScrollChip;
 
     private UiEventLogger mUiEventLogger;
-    private Runnable mOnDismissRunnable;
+    private ScreenshotViewCallback mCallbacks;
     private Animator mDismissAnimation;
 
     private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
@@ -195,8 +204,10 @@
 
         final Rect tmpRect = new Rect();
         mScreenshotPreview.getBoundsOnScreen(tmpRect);
+        tmpRect.inset((int) dpToPx(-SWIPE_PADDING_DP), (int) dpToPx(-SWIPE_PADDING_DP));
         touchRegion.op(tmpRect, Region.Op.UNION);
-        mActionsContainer.getBoundsOnScreen(tmpRect);
+        mActionsContainerBackground.getBoundsOnScreen(tmpRect);
+        tmpRect.inset((int) dpToPx(-SWIPE_PADDING_DP), (int) dpToPx(-SWIPE_PADDING_DP));
         touchRegion.op(tmpRect, Region.Op.UNION);
         mDismissButton.getBoundsOnScreen(tmpRect);
         touchRegion.op(tmpRect, Region.Op.UNION);
@@ -215,7 +226,9 @@
 
     @Override // View
     protected void onFinishInflate() {
+        mScreenshotStatic = requireNonNull(findViewById(R.id.global_screenshot_static));
         mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview));
+
         mActionsContainerBackground = requireNonNull(findViewById(
                 R.id.global_screenshot_actions_container_background));
         mActionsContainer = requireNonNull(findViewById(R.id.global_screenshot_actions_container));
@@ -238,6 +251,16 @@
             }
         });
 
+        int swipePaddingPx = (int) dpToPx(SWIPE_PADDING_DP);
+        TouchDelegate previewDelegate = new TouchDelegate(
+                new Rect(swipePaddingPx, swipePaddingPx, swipePaddingPx, swipePaddingPx),
+                mScreenshotPreview);
+        mScreenshotPreview.setTouchDelegate(previewDelegate);
+        TouchDelegate actionsDelegate = new TouchDelegate(
+                new Rect(swipePaddingPx, swipePaddingPx, swipePaddingPx, swipePaddingPx),
+                mActionsContainerBackground);
+        mActionsContainerBackground.setTouchDelegate(actionsDelegate);
+
         setFocusable(true);
         mScreenshotSelectorView.setFocusable(true);
         mScreenshotSelectorView.setFocusableInTouchMode(true);
@@ -272,9 +295,9 @@
      * Note: must be called before any other (non-constructor) method or null pointer exceptions
      * may occur.
      */
-    void init(UiEventLogger uiEventLogger, Runnable onDismissRunnable) {
+    void init(UiEventLogger uiEventLogger, ScreenshotViewCallback callbacks) {
         mUiEventLogger = uiEventLogger;
-        mOnDismissRunnable = onDismissRunnable;
+        mCallbacks = callbacks;
     }
 
     void takePartialScreenshot(Consumer<Rect> onPartialScreenshotSelected) {
@@ -414,8 +437,14 @@
                 mScreenshotPreview.setX(finalPos.x - bounds.width() * cornerScale / 2f);
                 mScreenshotPreview.setY(finalPos.y - bounds.height() * cornerScale / 2f);
                 requestLayout();
-                mScreenshotPreview.setOnTouchListener(new SwipeDismissHandler());
+
                 createScreenshotActionsShadeAnimation().start();
+
+                SwipeDismissHandler swipeDismissHandler = new SwipeDismissHandler();
+                mScreenshotPreview.setOnTouchListener(swipeDismissHandler);
+                mActionsContainer.setOnTouchListener(swipeDismissHandler);
+                mActionsContainerBackground.setOnTouchListener(swipeDismissHandler);
+                mBackgroundProtection.setOnTouchListener(swipeDismissHandler);
             }
         });
 
@@ -544,6 +573,7 @@
                             mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
                             animateDismissal();
                         });
+                actionChip.setAlpha(1);
                 mActionsView.addView(actionChip);
                 mSmartChips.add(actionChip);
             }
@@ -583,7 +613,7 @@
                     if (DEBUG_ANIM) {
                         Log.d(TAG, "after dismiss animation, calling onDismissRunnable.run()");
                     }
-                    mOnDismissRunnable.run();
+                    mCallbacks.onDismiss();
                 }
             }
         });
@@ -617,7 +647,7 @@
         mDismissButton.setVisibility(View.GONE);
         mScreenshotPreview.setVisibility(View.GONE);
         mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
-        mScreenshotPreview.setTranslationX(0);
+        mScreenshotStatic.setTranslationX(0);
         mScreenshotPreview.setTranslationY(0);
         mScreenshotPreview.setContentDescription(
                 mContext.getResources().getString(R.string.screenshot_preview_description));
@@ -675,7 +705,7 @@
         BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bitmap);
         if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
                 || bitmap.getHeight() == 0) {
-            Log.e(TAG,  "Can't create inset drawable, using 0 insets bitmap and insets create "
+            Log.e(TAG, "Can't create inset drawable, using 0 insets bitmap and insets create "
                     + "degenerate region: " + bitmap.getWidth() + "x" + bitmap.getHeight() + " "
                     + bitmapDrawable);
             return bitmapDrawable;
@@ -697,6 +727,10 @@
         }
     }
 
+    private float dpToPx(float dp) {
+        return dp * mDisplayMetrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
+    }
+
     class SwipeDismissHandler implements OnTouchListener {
 
         // if distance moved on ACTION_UP is less than this, register a click
@@ -707,11 +741,17 @@
 
         private final GestureDetector mGestureDetector;
         private final float mDismissStartX;
+        private final Rect mActionsRect = new Rect();
 
         private float mStartX;
         private float mStartY;
         private float mTranslationX = 0;
 
+        // tracks whether mStartX has been set for this interaction
+        private boolean mInteractionStarted = false;
+        // tracks whether we're dragging the UI (as opposed to scrolling the actions bar)
+        private boolean mIsDragging = false;
+
         SwipeDismissHandler() {
             GestureDetector.OnGestureListener gestureListener = new SwipeDismissGestureListener();
             mGestureDetector = new GestureDetector(mContext, gestureListener);
@@ -720,10 +760,16 @@
 
         @Override
         public boolean onTouch(View v, MotionEvent event) {
+            boolean gestureResult = mGestureDetector.onTouchEvent(event);
+            mCallbacks.onUserInteraction();
             if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+                mInteractionStarted = true;
                 mStartX = event.getRawX();
                 mStartY = event.getRawY();
+                return true;
             } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+                mInteractionStarted = false;
+                mIsDragging = false;
                 if (isPastDismissThreshold()
                         && (mDismissAnimation == null || !mDismissAnimation.isRunning())) {
                     if (DEBUG_INPUT) {
@@ -745,18 +791,45 @@
                     return true;
                 }
             }
-            return mGestureDetector.onTouchEvent(event);
+            return gestureResult;
         }
 
         class SwipeDismissGestureListener extends GestureDetector.SimpleOnGestureListener {
 
+            /**
+             * This is somewhat complicated to handle because we want to allow scrolling the actions
+             * bar (if it extends off the screen) as well as dismissing the UI horizontally by
+             * dragging the actions bar. In addition, we don't get the initial ACTION_DOWN because
+             * it is consumed by the action bar view.
+             *
+             * So, we use a gated system: first, keep track of the pointer location as we move;
+             * next, check whether the actions bar can scroll in the direction we're moving in. If
+             * it can, let the actions bar handle the event; otherwise, we've gone as far as we can
+             * and can start dragging the UI instead.
+             */
             @Override
             public boolean onScroll(
                     MotionEvent ev1, MotionEvent ev2, float distanceX, float distanceY) {
-                mTranslationX = ev2.getRawX() - ev1.getRawX();
-                mScreenshotPreview.setTranslationX(mTranslationX);
-                mDismissButton.setX(mDismissStartX + mTranslationX);
-                return true;
+                mActionsContainer.getBoundsOnScreen(mActionsRect);
+                if (!mInteractionStarted) {
+                    if (mActionsRect.contains((int) ev2.getRawX(), (int) ev2.getRawY())) {
+                        mStartX = ev2.getRawX();
+                        mInteractionStarted = true;
+                    }
+                } else {
+                    float distance = ev2.getRawX() - mStartX;
+                    if ((mIsDragging && distance * mTranslationX > 0)
+                            || !mActionsRect.contains((int) ev2.getRawX(), (int) ev2.getRawY())
+                            || !mActionsContainer.canScrollHorizontally(-1 * (int) distance)) {
+                        mIsDragging = true;
+                        mTranslationX = distance;
+                        mScreenshotStatic.setTranslationX(mTranslationX);
+                        return true;
+                    } else {
+                        mStartX = ev2.getRawX();
+                    }
+                }
+                return false;
             }
         }
 
@@ -772,23 +845,18 @@
             ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
             float startX = mTranslationX;
             float finalX = mDirectionLTR
-                    ? -1 * (mDismissStartX + mDismissButton.getWidth())
+                    ? -1 * (mActionsContainerBackground.getX()
+                    + mActionsContainerBackground.getWidth())
                     : mDisplayMetrics.widthPixels;
 
             anim.addUpdateListener(animation -> {
-                float translation = MathUtils.lerp(startX, finalX, animation.getAnimatedFraction());
-                mScreenshotPreview.setTranslationX(translation);
-                mDismissButton.setX(mDismissStartX + translation);
-
-                float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
-
-                mActionsContainer.setTranslationY(yDelta);
-                mActionsContainerBackground.setTranslationY(yDelta);
+                float translation = MathUtils.lerp(startX, finalX,
+                        animation.getAnimatedFraction());
+                mScreenshotStatic.setTranslationX(translation);
 
                 setAlpha(1 - animation.getAnimatedFraction());
             });
             anim.setDuration(400);
-
             return anim;
         }
 
@@ -801,15 +869,10 @@
             anim.addUpdateListener(animation -> {
                 float translation = MathUtils.lerp(
                         startX, finalX, animation.getAnimatedFraction());
-                mScreenshotPreview.setTranslationX(translation);
-                mDismissButton.setX(mDismissStartX + translation);
+                mScreenshotStatic.setTranslationX(translation);
             });
 
             return anim;
         }
-
-        private float dpToPx(float dp) {
-            return dp * mDisplayMetrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 6202057..9933438 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -26,8 +26,8 @@
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.SystemUI;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.wm.shell.splitscreen.DividerView;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.DividerView;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -41,7 +41,7 @@
         implements ShortcutKeyServiceProxy.Callbacks {
 
     private static final String TAG = "ShortcutKeyDispatcher";
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
 
     private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
     private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -55,7 +55,7 @@
     protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
 
     @Inject
-    public ShortcutKeyDispatcher(Context context, Optional<SplitScreen> splitScreenOptional) {
+    public ShortcutKeyDispatcher(Context context, Optional<LegacySplitScreen> splitScreenOptional) {
         super(context);
         mSplitScreenOptional = splitScreenOptional;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 9bd34ad..4b6d66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -484,8 +484,8 @@
                     stack.push(notificationChildren.get(i));
                 }
             }
-
-            row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry));
+            row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry),
+                    mAssistantFeedbackController.getFeedbackImageResource(entry));
             row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs());
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
index 87a3f07..a350c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -18,6 +18,7 @@
 
 import static android.service.notification.NotificationListenerService.Ranking;
 
+import android.app.NotificationManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -29,6 +30,7 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -47,6 +49,12 @@
             = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED);
     private ContentResolver mResolver;
 
+    public static final int STATUS_UNCHANGED = 0;
+    public static final int STATUS_ALERTED = 1;
+    public static final int STATUS_SILENCED = 2;
+    public static final int STATUS_PROMOTED = 3;
+    public static final int STATUS_DEMOTED = 4;
+
     private boolean mFeedbackEnabled;
 
     /** Injected constructor */
@@ -81,16 +89,88 @@
     }
 
     /**
-     * Determines whether to show feedback indicator. The feedback indicator will be shown if
-     * {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank or
-     * importance.
+     * Get the feedback status according to assistant's adjustments
+     *
+     * @param entry Notification Entry to show feedback for
+     */
+    public int getFeedbackStatus(NotificationEntry entry) {
+        if (!isFeedbackEnabled()) {
+            return STATUS_UNCHANGED;
+        }
+        Ranking ranking = entry.getRanking();
+        int oldImportance = ranking.getChannel().getImportance();
+        int newImportance = ranking.getImportance();
+        if (oldImportance < NotificationManager.IMPORTANCE_DEFAULT
+                && newImportance >= NotificationManager.IMPORTANCE_DEFAULT) {
+            return STATUS_ALERTED;
+        } else if (oldImportance >= NotificationManager.IMPORTANCE_DEFAULT
+                && newImportance < NotificationManager.IMPORTANCE_DEFAULT) {
+            return STATUS_SILENCED;
+        } else if (oldImportance < newImportance
+                || ranking.getRankingAdjustment() == ranking.RANKING_PROMOTED) {
+            return STATUS_PROMOTED;
+        } else if (oldImportance > newImportance
+                || ranking.getRankingAdjustment() == ranking.RANKING_DEMOTED) {
+            return STATUS_DEMOTED;
+        } else {
+            return STATUS_UNCHANGED;
+        }
+    }
+
+    /**
+     * Determines whether to show feedback indicator. The feedback indicator will be shown
+     * if {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank
+     * or importance.
      *
      * @param entry Notification Entry to show feedback for
      */
     public boolean showFeedbackIndicator(NotificationEntry entry) {
-        Ranking ranking = entry.getRanking();
-        return isFeedbackEnabled()
-                && (ranking.getImportance() != ranking.getChannel().getImportance()
-                || ranking.getRankingAdjustment() != Ranking.RANKING_UNCHANGED);
+        return getFeedbackStatus(entry) != STATUS_UNCHANGED;
+    }
+
+    /**
+     * Get the feedback indicator image resource according to assistant's changes on this
+     * notification's rank or importance.
+     *
+     * @param entry Notification Entry to show feedback for
+     */
+    public int getFeedbackImageResource(NotificationEntry entry) {
+        int feedbackStatus = getFeedbackStatus(entry);
+        switch (feedbackStatus) {
+            case STATUS_ALERTED:
+                return R.drawable.ic_feedback_alerted;
+            case STATUS_SILENCED:
+                return R.drawable.ic_feedback_silenced;
+            case STATUS_PROMOTED:
+                return R.drawable.ic_feedback_uprank;
+            case STATUS_DEMOTED:
+                return R.drawable.ic_feedback_downrank;
+            default:
+                return 0;
+        }
+    }
+
+    /**
+     * Get the inline settings description resource according to assistant's changes on this
+     * notification's rank or importance.
+     *
+     * @param entry Notification Entry to show feedback for
+     */
+    public int getInlineDescriptionResource(NotificationEntry entry) {
+        int feedbackStatus = getFeedbackStatus(entry);
+        switch (feedbackStatus) {
+            case STATUS_ALERTED:
+                return com.android.systemui.R.string.notification_channel_summary_automatic_alerted;
+            case STATUS_SILENCED:
+                return com.android.systemui.R.string
+                        .notification_channel_summary_automatic_silenced;
+            case STATUS_PROMOTED:
+                return com.android.systemui.R.string
+                        .notification_channel_summary_automatic_promoted;
+            case STATUS_DEMOTED:
+                return com.android.systemui.R.string.notification_channel_summary_automatic_demoted;
+            default:
+                return com.android.systemui.R.string.notification_channel_summary_automatic;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 1f9bc77..e58ea7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -59,7 +59,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.NotificationChannels;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.List;
 import java.util.Optional;
@@ -82,11 +82,11 @@
     private final CommandQueue mCommandQueue;
     private boolean mDockedStackExists;
     private KeyguardStateController mKeyguardStateController;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
 
     @Inject
     public InstantAppNotifier(Context context, CommandQueue commandQueue,
-            @UiBackground Executor uiBgExecutor, Optional<SplitScreen> splitScreenOptional) {
+            @UiBackground Executor uiBgExecutor, Optional<LegacySplitScreen> splitScreenOptional) {
         super(context);
         mSplitScreenOptional = splitScreenOptional;
         mCommandQueue = commandQueue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index c7ac403..998ae9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -30,12 +30,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import javax.inject.Inject;
 
 /**
@@ -75,9 +71,6 @@
     public void attach(NotifPipeline pipeline) {
         mNotifPipeline = pipeline;
 
-        // extend the lifetime of foreground notification services to show for at least 5 seconds
-        mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
-
         // filter out foreground service notifications that aren't necessary anymore
         mNotifPipeline.addPreGroupFilter(mNotifFilter);
 
@@ -119,64 +112,6 @@
     };
 
     /**
-     * Extends the lifetime of foreground notification services such that they show for at least
-     * five seconds
-     */
-    private final NotifLifetimeExtender mForegroundLifetimeExtender =
-            new NotifLifetimeExtender() {
-        private static final int MIN_FGS_TIME_MS = 5000;
-        private OnEndLifetimeExtensionCallback mEndCallback;
-        private Map<NotificationEntry, Runnable> mEndRunnables = new HashMap<>();
-
-        @Override
-        public String getName() {
-            return TAG;
-        }
-
-        @Override
-        public void setCallback(OnEndLifetimeExtensionCallback callback) {
-            mEndCallback = callback;
-        }
-
-        @Override
-        public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
-            if ((entry.getSbn().getNotification().flags
-                    & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
-                return false;
-            }
-
-            final long currTime = System.currentTimeMillis();
-            final boolean extendLife = currTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
-
-            if (extendLife) {
-                if (!mEndRunnables.containsKey(entry)) {
-                    final Runnable endExtensionRunnable = () -> {
-                        mEndRunnables.remove(entry);
-                        mEndCallback.onEndLifetimeExtension(
-                                mForegroundLifetimeExtender,
-                                entry);
-                    };
-
-                    final Runnable cancelRunnable = mMainExecutor.executeDelayed(
-                            endExtensionRunnable,
-                            MIN_FGS_TIME_MS - (currTime - entry.getSbn().getPostTime()));
-                    mEndRunnables.put(entry, cancelRunnable);
-                }
-            }
-
-            return extendLife;
-        }
-
-        @Override
-        public void cancelLifetimeExtension(NotificationEntry entry) {
-            Runnable cancelRunnable = mEndRunnables.remove(entry);
-            if (cancelRunnable != null) {
-                cancelRunnable.run();
-            }
-        }
-    };
-
-    /**
      * Puts foreground service notifications into its own section.
      */
     private final NotifSectioner mNotifSectioner = new NotifSectioner("ForegroundService") {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 10118e4..11b829c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1672,12 +1672,12 @@
         requestLayout();
     }
 
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, int resId) {
         if (mIsSummaryWithChildren) {
-            mChildrenContainer.showFeedbackIcon(show);
+            mChildrenContainer.showFeedbackIcon(show, resId);
         }
-        mPrivateLayout.showFeedbackIcon(show);
-        mPublicLayout.showFeedbackIcon(show);
+        mPrivateLayout.showFeedbackIcon(show, resId);
+        mPublicLayout.showFeedbackIcon(show, resId);
     }
 
     /** Sets the last time the notification being displayed audibly alerted the user. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 2ff43d0..85f556f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -54,7 +54,8 @@
             R.id.bottom_roundess_animator_end_tag,
             R.id.bottom_roundess_animator_start_tag);
     private static final AnimationProperties ROUNDNESS_PROPERTIES =
-            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            new AnimationProperties().setDuration(
+                    StackStateAnimator.ANIMATION_DURATION_CORNER_RADIUS);
     private static final Path EMPTY_PATH = new Path();
 
     private final Rect mOutlineRect = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 73e0804..ba03d01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -69,6 +69,7 @@
     private float mContentTranslation;
     protected boolean mLastInSection;
     protected boolean mFirstInSection;
+    boolean mIsBeingSwiped;
 
     public ExpandableView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -173,6 +174,14 @@
         return false;
     }
 
+    public void setIsBeingSwiped(boolean swiped) {
+        mIsBeingSwiped = swiped;
+    }
+
+    public boolean isBeingSwiped() {
+        return mIsBeingSwiped;
+    }
+
     public boolean isHeadsUpAnimatingAway() {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
index 149ee8c..35f3561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
@@ -16,10 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
-
 import android.annotation.SuppressLint;
 import android.app.Notification;
 import android.content.Context;
@@ -30,6 +26,7 @@
 import android.os.RemoteException;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
+import android.text.Html;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -138,30 +135,30 @@
         no.setVisibility(View.VISIBLE);
         yes.setOnClickListener(this::positiveFeedback);
         no.setOnClickListener(this::negativeFeedback);
-        prompt.setText(getPrompt());
+        prompt.setText(Html.fromHtml(getPrompt()));
     }
 
     @SuppressLint("DefaultLocale")
     private String getPrompt() {
         StringBuilder sb = new StringBuilder();
-        int oldImportance = mRanking.getChannel().getImportance();
-        int newImportance = mRanking.getImportance();
-        int ranking = mRanking.getRankingAdjustment();
+        int status = mFeedbackController.getFeedbackStatus(mEntry);
         if (DEBUG) {
             sb.append(String.format(
                     "[DEBUG]: oldImportance=%d, newImportance=%d, ranking=%d\n\n",
                     mRanking.getChannel().getImportance(), mRanking.getImportance(),
                     mRanking.getRankingAdjustment()));
         }
-        if (oldImportance >= IMPORTANCE_DEFAULT && newImportance < IMPORTANCE_DEFAULT) {
-            sb.append(mContext.getString(R.string.feedback_silenced));
-        } else if (newImportance > oldImportance || ranking == RANKING_PROMOTED) {
-            sb.append(mContext.getString(R.string.feedback_promoted));
-        } else if (newImportance < oldImportance || ranking == RANKING_DEMOTED) {
-            sb.append(mContext.getString(R.string.feedback_demoted));
+        if (status == mFeedbackController.STATUS_ALERTED) {
+            sb.append(mContext.getText(R.string.feedback_alerted));
+        } else if (status == mFeedbackController.STATUS_SILENCED) {
+            sb.append(mContext.getText(R.string.feedback_silenced));
+        } else if (status == mFeedbackController.STATUS_PROMOTED) {
+            sb.append(mContext.getText(R.string.feedback_promoted));
+        } else if (status == mFeedbackController.STATUS_DEMOTED) {
+            sb.append(mContext.getText(R.string.feedback_demoted));
         }
         sb.append(" ");
-        sb.append(mContext.getString(R.string.feedback_prompt));
+        sb.append(mContext.getText(R.string.feedback_prompt));
 
         return sb.toString();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 74e6c00..475f627 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1586,15 +1586,15 @@
         return null;
     }
 
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, int resId) {
         if (mContractedChild != null) {
-            mContractedWrapper.showFeedbackIcon(show);
+            mContractedWrapper.showFeedbackIcon(show, resId);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.showFeedbackIcon(show);
+            mExpandedWrapper.showFeedbackIcon(show, resId);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.showFeedbackIcon(show);
+            mHeadsUpWrapper.showFeedbackIcon(show, resId);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index c4f0098..2fd17a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -378,7 +378,7 @@
                 mDeviceProvisionedController.isDeviceProvisioned(),
                 row.getIsNonblockable(),
                 mHighPriorityProvider.isHighPriority(row.getEntry()),
-                mAssistantFeedbackController.isFeedbackEnabled());
+                mAssistantFeedbackController);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 6ff5ed1..d12d98e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -41,6 +41,7 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.service.notification.StatusBarNotification;
+import android.text.Html;
 import android.text.TextUtils;
 import android.transition.ChangeBounds;
 import android.transition.Fade;
@@ -60,6 +61,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import java.lang.annotation.Retention;
@@ -96,6 +98,7 @@
     private PackageManager mPm;
     private MetricsLogger mMetricsLogger;
     private ChannelEditorDialogController mChannelEditorDialogController;
+    private AssistantFeedbackController mAssistantFeedbackController;
 
     private String mPackageName;
     private String mAppName;
@@ -200,12 +203,13 @@
             boolean isDeviceProvisioned,
             boolean isNonblockable,
             boolean wasShownHighPriority,
-            boolean showAutomaticSetting)
+            AssistantFeedbackController assistantFeedbackController)
             throws RemoteException {
         mINotificationManager = iNotificationManager;
         mMetricsLogger = Dependency.get(MetricsLogger.class);
         mOnUserInteractionCallback = onUserInteractionCallback;
         mChannelEditorDialogController = channelEditorDialogController;
+        mAssistantFeedbackController = assistantFeedbackController;
         mPackageName = pkg;
         mUniqueChannelsInRow = uniqueChannelsInRow;
         mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
@@ -222,7 +226,7 @@
         mAppUid = mSbn.getUid();
         mDelegatePkg = mSbn.getOpPkg();
         mIsDeviceProvisioned = isDeviceProvisioned;
-        mShowAutomaticSetting = showAutomaticSetting;
+        mShowAutomaticSetting = mAssistantFeedbackController.isFeedbackEnabled();
         mUiEventLogger = uiEventLogger;
 
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
@@ -280,6 +284,8 @@
 
         View automatic = findViewById(R.id.automatic);
         if (mShowAutomaticSetting) {
+            mAutomaticDescriptionView.setText(Html.fromHtml(mContext.getText(
+                    mAssistantFeedbackController.getInlineDescriptionResource(mEntry)).toString()));
             automatic.setVisibility(VISIBLE);
             automatic.setOnClickListener(mOnAutomatic);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 7c5d4a3..152527f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -29,6 +29,7 @@
 import android.view.ViewGroup.MarginLayoutParams;
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.TextView;
 
@@ -131,8 +132,11 @@
 
     /** Shows or hides feedback indicator */
     @Override
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, int resId) {
         mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+        if (show && mFeedbackIcon instanceof ImageButton) {
+            ((ImageButton) mFeedbackIcon).setImageResource(resId);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 2d706a4..04cbe87c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -103,7 +103,7 @@
     /**
      * Shows or hides feedback icon.
      */
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, int resId) {
     }
 
     public void onReinflated() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 885048d..2c501cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.util.MathUtils;
-import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationShelf;
@@ -31,19 +30,16 @@
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider;
 
-import java.util.ArrayList;
-
 /**
  * A global state to track all input states for the algorithm.
  */
 public class AmbientState {
 
     private static final float MAX_PULSE_HEIGHT = 100000f;
+    private static final boolean NOTIFICATIONS_HAVE_SHADOWS = false;
 
     private final SectionProvider mSectionProvider;
     private int mScrollY;
-    private int mAnchorViewIndex;
-    private int mAnchorViewY;
     private boolean mDimmed;
     private ActivatableNotificationView mActivatedChild;
     private float mOverScrollTopAmount;
@@ -106,7 +102,7 @@
     }
 
     private static int getBaseHeight(int zdistanceBetweenElements) {
-        return 4 * zdistanceBetweenElements;
+        return NOTIFICATIONS_HAVE_SHADOWS ? 4 * zdistanceBetweenElements : 0;
     }
 
     /**
@@ -140,27 +136,6 @@
     }
 
     /**
-     * Index of the child view whose Y position on screen is returned by {@link #getAnchorViewY()}.
-     * Other views are laid out outwards from this view in both directions.
-     */
-    public int getAnchorViewIndex() {
-        return mAnchorViewIndex;
-    }
-
-    public void setAnchorViewIndex(int anchorViewIndex) {
-        mAnchorViewIndex = anchorViewIndex;
-    }
-
-    /** Current Y position of the view at {@link #getAnchorViewIndex()}. */
-    public int getAnchorViewY() {
-        return mAnchorViewY;
-    }
-
-    public void setAnchorViewY(int anchorViewY) {
-        mAnchorViewY = anchorViewY;
-    }
-
-    /**
      * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
      *               translucent and everything is scaled back a bit.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 601fc19..a56ae7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1300,12 +1300,12 @@
     /**
      * Shows or hides feedback icon.
      */
-    public void showFeedbackIcon(boolean show) {
+    public void showFeedbackIcon(boolean show, int resId) {
         if (mNotificationHeaderWrapper != null) {
-            mNotificationHeaderWrapper.showFeedbackIcon(show);
+            mNotificationHeaderWrapper.showFeedbackIcon(show, resId);
         }
         if (mNotificationHeaderWrapperLowPriority != null) {
-            mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show);
+            mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resId);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index f9d7c1f..3160071 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -67,7 +67,7 @@
         }
     }
 
-    private boolean updateViewWithoutCallback(ExpandableView view,
+    boolean updateViewWithoutCallback(ExpandableView view,
             boolean animate) {
         float topRoundness = getRoundness(view, true /* top */);
         float bottomRoundness = getRoundness(view, false /* top */);
@@ -107,7 +107,9 @@
     }
 
     private float getRoundness(ExpandableView view, boolean top) {
-        if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
+        if ((view.isPinned()
+                || view.isBeingSwiped()
+                || (view.isHeadsUpAnimatingAway()) && !mExpanded)) {
             return 1.0f;
         }
         if (isFirstInSection(view, true /* include first section */) && top) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 4f7e14b..6c8cdf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -73,7 +73,6 @@
 
     private lateinit var parent: NotificationStackScrollLayout
     private var initialized = false
-    private var onClearSilentNotifsClickListener: View.OnClickListener? = null
 
     @VisibleForTesting
     val silentHeaderView: SectionHeaderView?
@@ -441,11 +440,6 @@
         }
     }
 
-    /** Listener for when the "clear all" button is clicked on the gentle notification header. */
-    fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) {
-        onClearSilentNotifsClickListener = listener
-    }
-
     fun setHeaderForegroundColor(@ColorInt color: Int) {
         peopleHeaderView?.setForegroundColor(color)
         silentHeaderView?.setForegroundColor(color)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 4487142..0dc824f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -19,7 +19,6 @@
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
-import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING;
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
@@ -164,9 +163,6 @@
 
     private float mExpandedHeight;
     private int mOwnScrollY;
-
-    private View mScrollAnchorView;
-    private int mScrollAnchorViewY;
     private int mMaxLayoutHeight;
 
     private VelocityTracker mVelocityTracker;
@@ -387,7 +383,6 @@
             }
         }
     };
-    private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
     private boolean mPulsing;
     private boolean mScrollable;
     private View mForcedScroll;
@@ -423,9 +418,6 @@
     private int mCachedBackgroundColor;
     private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
     private Runnable mReflingAndAnimateScroll = () -> {
-        if (ANCHOR_SCROLLING) {
-            maybeReflingScroller();
-        }
         animateScroll();
     };
     private int mCornerRadius;
@@ -480,23 +472,12 @@
     private final ScrollAdapter mScrollAdapter = new ScrollAdapter() {
         @Override
         public boolean isScrolledToTop() {
-            if (ANCHOR_SCROLLING) {
-                updateScrollAnchor();
-                // TODO: once we're recycling this will need to check the adapter position of the
-                //  child
-                return mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY >= 0;
-            } else {
-                return mOwnScrollY == 0;
-            }
+            return mOwnScrollY == 0;
         }
 
         @Override
         public boolean isScrolledToBottom() {
-            if (ANCHOR_SCROLLING) {
-                return getMaxPositiveScrollAmount() <= 0;
-            } else {
-                return mOwnScrollY >= getScrollRange();
-            }
+            return mOwnScrollY >= getScrollRange();
         }
 
         @Override
@@ -519,12 +500,6 @@
         mSectionsManager = notificationSectionsManager;
 
         mSectionsManager.initialize(this, LayoutInflater.from(context));
-        mSectionsManager.setOnClearSilentNotifsClickListener(v -> {
-            // Leave the shade open if there will be other notifs left over to clear
-            final boolean closeShade =
-                    !mController.hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
-            clearNotifications(ROWS_GENTLE, closeShade);
-        });
         mSections = mSectionsManager.createSectionsForBuckets();
 
         mAmbientState = new AmbientState(context, mSectionsManager);
@@ -665,30 +640,6 @@
         }
     }
 
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        if (DEBUG && ANCHOR_SCROLLING) {
-            if (mScrollAnchorView instanceof ExpandableNotificationRow) {
-                canvas.drawRect(0,
-                        mScrollAnchorView.getTranslationY(),
-                        getWidth(),
-                        mScrollAnchorView.getTranslationY()
-                                + ((ExpandableNotificationRow) mScrollAnchorView).getActualHeight(),
-                        mDebugPaint);
-                canvas.drawText(Integer.toString(mScrollAnchorViewY), getWidth() - 200,
-                        mScrollAnchorView.getTranslationY() + 30, mDebugPaint);
-                int y = (int) mShelf.getTranslationY();
-                canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
-            }
-            canvas.drawText(Integer.toString(getMaxNegativeScrollAmount()), getWidth() - 100,
-                    getTopPadding() + 30, mDebugPaint);
-            canvas.drawText(Integer.toString(getMaxPositiveScrollAmount()), getWidth() - 100,
-                    getHeight() - 30, mDebugPaint);
-        }
-    }
-
     @ShadeViewRefactor(RefactorComponent.DECORATOR)
     private void drawBackground(Canvas canvas) {
         int lockScreenLeft = mSidePaddings;
@@ -823,13 +774,6 @@
         if (!mShouldDrawNotificationBackground) {
             return;
         }
-        final boolean newFlowHideShelf = Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* on by default */) == 1;
-        if (newFlowHideShelf) {
-            mBackgroundPaint.setColor(Color.TRANSPARENT);
-            invalidate();
-            return;
-        }
         // Interpolate between semi-transparent notification panel background color
         // and white AOD separator.
         float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */,
@@ -996,10 +940,6 @@
         mListener = listener;
     }
 
-    public void setScrollAnchorView(View scrollAnchorView) {
-        mScrollAnchorView = scrollAnchorView;
-    }
-
     @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
@@ -1030,12 +970,7 @@
         mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
                 ? 0
                 : mScroller.getCurrVelocity());
-        if (ANCHOR_SCROLLING) {
-            mAmbientState.setAnchorViewIndex(indexOfChild(mScrollAnchorView));
-            mAmbientState.setAnchorViewY(mScrollAnchorViewY);
-        } else {
-            mAmbientState.setScrollY(mOwnScrollY);
-        }
+        mAmbientState.setScrollY(mOwnScrollY);
         mStackScrollAlgorithm.resetViewStates(mAmbientState, getSpeedBumpIndex());
         if (!isCurrentlyAnimating() && !mNeedsAnimation) {
             applyCurrentState();
@@ -1081,18 +1016,16 @@
         if (mChildrenToAddAnimated.isEmpty()) {
             return;
         }
-        if (!ANCHOR_SCROLLING) {
-            for (int i = 0; i < getChildCount(); i++) {
-                ExpandableView child = (ExpandableView) getChildAt(i);
-                if (mChildrenToAddAnimated.contains(child)) {
-                    final int startingPosition = getPositionInLinearLayout(child);
-                    final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements;
-                    if (startingPosition < mOwnScrollY) {
-                        // This child starts off screen, so let's keep it offscreen to keep the
-                        // others visible
+        for (int i = 0; i < getChildCount(); i++) {
+            ExpandableView child = (ExpandableView) getChildAt(i);
+            if (mChildrenToAddAnimated.contains(child)) {
+                final int startingPosition = getPositionInLinearLayout(child);
+                final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements;
+                if (startingPosition < mOwnScrollY) {
+                    // This child starts off screen, so let's keep it offscreen to keep the
+                    // others visible
 
-                        setOwnScrollY(mOwnScrollY + childHeight);
-                    }
+                    setOwnScrollY(mOwnScrollY + childHeight);
                 }
             }
         }
@@ -1110,17 +1043,11 @@
             int positionInLinearLayout = getPositionInLinearLayout(expandableView);
             int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
             int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
-
-            if (ANCHOR_SCROLLING) {
-                // TODO
-            } else {
-                targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
-
-                // Only apply the scroll if we're scrolling the view upwards, or the view is so
-                // far up that it is not visible anymore.
-                if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
-                    setOwnScrollY(targetScroll);
-                }
+            targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
+            // Only apply the scroll if we're scrolling the view upwards, or the view is so
+            // far up that it is not visible anymore.
+            if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+                setOwnScrollY(targetScroll);
             }
         }
     }
@@ -1155,13 +1082,9 @@
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void clampScrollPosition() {
-        if (ANCHOR_SCROLLING) {
-            // TODO
-        } else {
-            int scrollRange = getScrollRange();
-            if (scrollRange < mOwnScrollY) {
-                setOwnScrollY(scrollRange);
-            }
+        int scrollRange = getScrollRange();
+        if (scrollRange < mOwnScrollY) {
+            setOwnScrollY(scrollRange);
         }
     }
 
@@ -1425,12 +1348,6 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.ADAPTER)
-    public int getFirstItemMinHeight() {
-        final ExpandableView firstChild = getFirstChildNotGone();
-        return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.ADAPTER)
     public void setQsContainer(ViewGroup qsContainer) {
         mQsContainer = qsContainer;
     }
@@ -1454,36 +1371,6 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
-    public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
-        getLocationOnScreen(mTempInt2);
-        float localTouchY = touchY - mTempInt2[1];
-
-        ExpandableView closestChild = null;
-        float minDist = Float.MAX_VALUE;
-
-        // find the view closest to the location, accounting for GONE views
-        final int count = getChildCount();
-        for (int childIdx = 0; childIdx < count; childIdx++) {
-            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
-            if (slidingChild.getVisibility() == GONE
-                    || slidingChild instanceof StackScrollerDecorView) {
-                continue;
-            }
-            float childTop = slidingChild.getTranslationY();
-            float top = childTop + slidingChild.getClipTopAmount();
-            float bottom = childTop + slidingChild.getActualHeight()
-                    - slidingChild.getClipBottomAmount();
-
-            float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY));
-            if (dist < minDist) {
-                closestChild = slidingChild;
-                minDist = dist;
-            }
-        }
-        return closestChild;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ExpandableView getChildAtPosition(float touchX, float touchY) {
         return getChildAtPosition(
                 touchX, touchY, true /* requireMinHeight */, true /* ignoreDecors */);
@@ -1559,21 +1446,17 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public boolean scrollTo(View v) {
         ExpandableView expandableView = (ExpandableView) v;
-        if (ANCHOR_SCROLLING) {
-            // TODO
-        } else {
-            int positionInLinearLayout = getPositionInLinearLayout(v);
-            int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
-            int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
+        int positionInLinearLayout = getPositionInLinearLayout(v);
+        int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+        int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
 
-            // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
-            // that it is not visible anymore.
-            if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
-                mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
-                mDontReportNextOverScroll = true;
-                animateScroll();
-                return true;
-            }
+        // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+        // that it is not visible anymore.
+        if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+            mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
+            mDontReportNextOverScroll = true;
+            animateScroll();
+            return true;
         }
         return false;
     }
@@ -1600,20 +1483,16 @@
             mWaterfallTopInset = cutout.getWaterfallInsets().top;
         }
 
-        if (ANCHOR_SCROLLING) {
-            // TODO
-        } else {
-            int range = getScrollRange();
-            if (mOwnScrollY > range) {
-                // HACK: We're repeatedly getting staggered insets here while the IME is
-                // animating away. To work around that we'll wait until things have settled.
-                removeCallbacks(mReclamp);
-                postDelayed(mReclamp, 50);
-            } else if (mForcedScroll != null) {
-                // The scroll was requested before we got the actual inset - in case we need
-                // to scroll up some more do so now.
-                scrollTo(mForcedScroll);
-            }
+        int range = getScrollRange();
+        if (mOwnScrollY > range) {
+            // HACK: We're repeatedly getting staggered insets here while the IME is
+            // animating away. To work around that we'll wait until things have settled.
+            removeCallbacks(mReclamp);
+            postDelayed(mReclamp, 50);
+        } else if (mForcedScroll != null) {
+            // The scroll was requested before we got the actual inset - in case we need
+            // to scroll up some more do so now.
+            scrollTo(mForcedScroll);
         }
         return insets;
     }
@@ -1622,12 +1501,8 @@
     private Runnable mReclamp = new Runnable() {
         @Override
         public void run() {
-            if (ANCHOR_SCROLLING) {
-                // TODO
-            } else {
-                int range = getScrollRange();
-                mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
-            }
+            int range = getScrollRange();
+            mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
             mDontReportNextOverScroll = true;
             mDontClampNextScroll = true;
             animateScroll();
@@ -1701,39 +1576,20 @@
         }
         // Top overScroll might not grab all scrolling motion,
         // we have to scroll as well.
-        if (ANCHOR_SCROLLING) {
-            float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
-            // TODO: once we're recycling this will need to check the adapter position of the child
-            ExpandableView lastRow = getLastRowNotGone();
-            if (lastRow != null && !lastRow.isInShelf()) {
-                float distanceToMax = Math.max(0, getMaxPositiveScrollAmount());
-                if (scrollAmount > distanceToMax) {
-                    float currentBottomPixels = getCurrentOverScrolledPixels(false);
-                    // We overScroll on the bottom
-                    setOverScrolledPixels(currentBottomPixels + (scrollAmount - distanceToMax),
-                            false /* onTop */,
-                            false /* animate */);
-                    mScrollAnchorViewY -= distanceToMax;
-                    scrollAmount = 0f;
-                }
+        float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
+        float newScrollY = mOwnScrollY + scrollAmount;
+        if (newScrollY > range) {
+            if (!mExpandedInThisMotion) {
+                float currentBottomPixels = getCurrentOverScrolledPixels(false);
+                // We overScroll on the bottom
+                setOverScrolledPixels(currentBottomPixels + newScrollY - range,
+                        false /* onTop */,
+                        false /* animate */);
             }
-            return scrollAmount;
-        } else {
-            float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
-            float newScrollY = mOwnScrollY + scrollAmount;
-            if (newScrollY > range) {
-                if (!mExpandedInThisMotion) {
-                    float currentBottomPixels = getCurrentOverScrolledPixels(false);
-                    // We overScroll on the bottom
-                    setOverScrolledPixels(currentBottomPixels + newScrollY - range,
-                            false /* onTop */,
-                            false /* animate */);
-                }
-                setOwnScrollY(range);
-                scrollAmount = 0.0f;
-            }
-            return scrollAmount;
+            setOwnScrollY(range);
+            scrollAmount = 0.0f;
         }
+        return scrollAmount;
     }
 
     /**
@@ -1754,37 +1610,18 @@
         }
         // Bottom overScroll might not grab all scrolling motion,
         // we have to scroll as well.
-        if (ANCHOR_SCROLLING) {
-            float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
-            // TODO: once we're recycling this will need to check the adapter position of the child
-            ExpandableView firstChild = getFirstChildNotGone();
-            float top = firstChild.getTranslationY();
-            float distanceToTop = mScrollAnchorView.getTranslationY() - top - mScrollAnchorViewY;
-            if (distanceToTop < -scrollAmount) {
-                float currentTopPixels = getCurrentOverScrolledPixels(true);
-                // We overScroll on the top
-                setOverScrolledPixels(currentTopPixels + (-scrollAmount - distanceToTop),
-                        true /* onTop */,
-                        false /* animate */);
-                mScrollAnchorView = firstChild;
-                mScrollAnchorViewY = 0;
-                scrollAmount = 0f;
-            }
-            return scrollAmount;
-        } else {
-            float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
-            float newScrollY = mOwnScrollY + scrollAmount;
-            if (newScrollY < 0) {
-                float currentTopPixels = getCurrentOverScrolledPixels(true);
-                // We overScroll on the top
-                setOverScrolledPixels(currentTopPixels - newScrollY,
-                        true /* onTop */,
-                        false /* animate */);
-                setOwnScrollY(0);
-                scrollAmount = 0.0f;
-            }
-            return scrollAmount;
+        float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
+        float newScrollY = mOwnScrollY + scrollAmount;
+        if (newScrollY < 0) {
+            float currentTopPixels = getCurrentOverScrolledPixels(true);
+            // We overScroll on the top
+            setOverScrolledPixels(currentTopPixels - newScrollY,
+                    true /* onTop */,
+                    false /* animate */);
+            setOwnScrollY(0);
+            scrollAmount = 0.0f;
         }
+        return scrollAmount;
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -1819,42 +1656,23 @@
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void animateScroll() {
         if (mScroller.computeScrollOffset()) {
-            if (ANCHOR_SCROLLING) {
-                int oldY = mLastScrollerY;
-                int y = mScroller.getCurrY();
-                int deltaY = y - oldY;
-                if (deltaY != 0) {
-                    int maxNegativeScrollAmount = getMaxNegativeScrollAmount();
-                    int maxPositiveScrollAmount = getMaxPositiveScrollAmount();
-                    if ((maxNegativeScrollAmount < 0 && deltaY < maxNegativeScrollAmount)
-                            || (maxPositiveScrollAmount > 0 && deltaY > maxPositiveScrollAmount)) {
-                        // This frame takes us into overscroll, so set the max overscroll based on
-                        // the current velocity
-                        setMaxOverScrollFromCurrentVelocity();
-                    }
-                    customOverScrollBy(deltaY, oldY, 0, (int) mMaxOverScroll);
-                    mLastScrollerY = y;
-                }
-            } else {
-                int oldY = mOwnScrollY;
-                int y = mScroller.getCurrY();
+            int oldY = mOwnScrollY;
+            int y = mScroller.getCurrY();
 
-                if (oldY != y) {
-                    int range = getScrollRange();
-                    if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
-                        // This frame takes us into overscroll, so set the max overscroll based on
-                        // the current velocity
-                        setMaxOverScrollFromCurrentVelocity();
-                    }
-
-                    if (mDontClampNextScroll) {
-                        range = Math.max(range, oldY);
-                    }
-                    customOverScrollBy(y - oldY, oldY, range,
-                            (int) (mMaxOverScroll));
+            if (oldY != y) {
+                int range = getScrollRange();
+                if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
+                    // This frame takes us into overscroll, so set the max overscroll based on
+                    // the current velocity
+                    setMaxOverScrollFromCurrentVelocity();
                 }
+
+                if (mDontClampNextScroll) {
+                    range = Math.max(range, oldY);
+                }
+                customOverScrollBy(y - oldY, oldY, range,
+                        (int) (mMaxOverScroll));
             }
-
             postOnAnimation(mReflingAndAnimateScroll);
         } else {
             mDontClampNextScroll = false;
@@ -1877,9 +1695,7 @@
      *
      * This method performs the determination of whether we're exceeding the overscroll and clamps
      * the scroll amount if so.  The actual scrolling/overscrolling happens in
-     * {@link #onCustomOverScrolled(int, boolean)} (absolute scrolling) or
-     * {@link #onCustomOverScrolledBy(int, boolean)} (anchor scrolling).
-     *
+     * {@link #onCustomOverScrolled(int, boolean)}
      * @param deltaY         The (signed) number of pixels to scroll.
      * @param scrollY        The current scroll position (absolute scrolling only).
      * @param scrollRangeY   The maximum allowable scroll position (absolute scrolling only).
@@ -1887,44 +1703,20 @@
      */
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void customOverScrollBy(int deltaY, int scrollY, int scrollRangeY, int maxOverScrollY) {
-        if (ANCHOR_SCROLLING) {
-            boolean clampedY = false;
-            if (deltaY < 0) {
-                int maxScrollAmount = getMaxNegativeScrollAmount();
-                if (maxScrollAmount > Integer.MIN_VALUE) {
-                    maxScrollAmount -= maxOverScrollY;
-                    if (deltaY < maxScrollAmount) {
-                        deltaY = maxScrollAmount;
-                        clampedY = true;
-                    }
-                }
-            } else {
-                int maxScrollAmount = getMaxPositiveScrollAmount();
-                if (maxScrollAmount < Integer.MAX_VALUE) {
-                    maxScrollAmount += maxOverScrollY;
-                    if (deltaY > maxScrollAmount) {
-                        deltaY = maxScrollAmount;
-                        clampedY = true;
-                    }
-                }
-            }
-            onCustomOverScrolledBy(deltaY, clampedY);
-        } else {
-            int newScrollY = scrollY + deltaY;
-            final int top = -maxOverScrollY;
-            final int bottom = maxOverScrollY + scrollRangeY;
+        int newScrollY = scrollY + deltaY;
+        final int top = -maxOverScrollY;
+        final int bottom = maxOverScrollY + scrollRangeY;
 
-            boolean clampedY = false;
-            if (newScrollY > bottom) {
-                newScrollY = bottom;
-                clampedY = true;
-            } else if (newScrollY < top) {
-                newScrollY = top;
-                clampedY = true;
-            }
-
-            onCustomOverScrolled(newScrollY, clampedY);
+        boolean clampedY = false;
+        if (newScrollY > bottom) {
+            newScrollY = bottom;
+            clampedY = true;
+        } else if (newScrollY < top) {
+            newScrollY = top;
+            clampedY = true;
         }
+
+        onCustomOverScrolled(newScrollY, clampedY);
     }
 
     /**
@@ -2043,35 +1835,6 @@
     }
 
     /**
-     * Scrolls by the given delta, overscrolling if needed.  If called during a fling and the delta
-     * would cause us to exceed the provided maximum overscroll, springs back instead.
-     *
-     * @param deltaY   The (signed) number of pixels to scroll.
-     * @param clampedY Whether this value was clamped by the calling method, meaning we've reached
-     *                 the overscroll limit.
-     */
-    private void onCustomOverScrolledBy(int deltaY, boolean clampedY) {
-        assert ANCHOR_SCROLLING;
-        mScrollAnchorViewY -= deltaY;
-        // Treat animating scrolls differently; see #computeScroll() for why.
-        if (!mScroller.isFinished()) {
-            if (clampedY) {
-                springBack();
-            } else {
-                float overScrollTop = getCurrentOverScrollAmount(true /* top */);
-                if (mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0) {
-                    notifyOverscrollTopListener(mScrollAnchorViewY,
-                            isRubberbanded(true /* onTop */));
-                } else {
-                    notifyOverscrollTopListener(overScrollTop, isRubberbanded(true /* onTop */));
-                }
-            }
-        }
-        updateScrollAnchor();
-        updateOnScrollChange();
-    }
-
-    /**
      * Scrolls to the given position, overscrolling if needed.  If called during a fling and the
      * position exceeds the provided maximum overscroll, springs back instead.
      *
@@ -2081,7 +1844,6 @@
      */
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void onCustomOverScrolled(int scrollY, boolean clampedY) {
-        assert !ANCHOR_SCROLLING;
         // Treat animating scrolls differently; see #computeScroll() for why.
         if (!mScroller.isFinished()) {
             setOwnScrollY(scrollY);
@@ -2106,45 +1868,25 @@
      */
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void springBack() {
-        if (ANCHOR_SCROLLING) {
-            boolean overScrolledTop = mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0;
-            int maxPositiveScrollAmount = getMaxPositiveScrollAmount();
-            boolean overscrolledBottom = maxPositiveScrollAmount < 0;
-            if (overScrolledTop || overscrolledBottom) {
-                float newAmount;
-                if (overScrolledTop) {
-                    newAmount = mScrollAnchorViewY;
-                    mScrollAnchorViewY = 0;
-                    mDontReportNextOverScroll = true;
-                } else {
-                    newAmount = -maxPositiveScrollAmount;
-                    mScrollAnchorViewY -= maxPositiveScrollAmount;
-                }
-                setOverScrollAmount(newAmount, overScrolledTop, false);
-                setOverScrollAmount(0.0f, overScrolledTop, true);
-                mScroller.forceFinished(true);
+        int scrollRange = getScrollRange();
+        boolean overScrolledTop = mOwnScrollY <= 0;
+        boolean overScrolledBottom = mOwnScrollY >= scrollRange;
+        if (overScrolledTop || overScrolledBottom) {
+            boolean onTop;
+            float newAmount;
+            if (overScrolledTop) {
+                onTop = true;
+                newAmount = -mOwnScrollY;
+                setOwnScrollY(0);
+                mDontReportNextOverScroll = true;
+            } else {
+                onTop = false;
+                newAmount = mOwnScrollY - scrollRange;
+                setOwnScrollY(scrollRange);
             }
-        } else {
-            int scrollRange = getScrollRange();
-            boolean overScrolledTop = mOwnScrollY <= 0;
-            boolean overScrolledBottom = mOwnScrollY >= scrollRange;
-            if (overScrolledTop || overScrolledBottom) {
-                boolean onTop;
-                float newAmount;
-                if (overScrolledTop) {
-                    onTop = true;
-                    newAmount = -mOwnScrollY;
-                    setOwnScrollY(0);
-                    mDontReportNextOverScroll = true;
-                } else {
-                    onTop = false;
-                    newAmount = mOwnScrollY - scrollRange;
-                    setOwnScrollY(scrollRange);
-                }
-                setOverScrollAmount(newAmount, onTop, false);
-                setOverScrollAmount(0.0f, onTop, true);
-                mScroller.forceFinished(true);
-            }
+            setOverScrollAmount(newAmount, onTop, false);
+            setOverScrollAmount(0.0f, onTop, true);
+            mScroller.forceFinished(true);
         }
     }
 
@@ -2183,25 +1925,6 @@
     }
 
     /**
-     * @return the child before the given view which has visibility unequal to GONE
-     */
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public ExpandableView getViewBeforeView(ExpandableView view) {
-        ExpandableView previousView = null;
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (child == view) {
-                return previousView;
-            }
-            if (child.getVisibility() != View.GONE) {
-                previousView = (ExpandableView) child;
-            }
-        }
-        return null;
-    }
-
-    /**
      * @return The first child which has visibility unequal to GONE which is currently below the
      * given translationY or equal to it.
      */
@@ -2334,8 +2057,7 @@
             ExpandableView current,
             int visibleIndex
     ) {
-       return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager,
-                mAmbientState.getAnchorViewIndex(), visibleIndex, current,
+       return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, visibleIndex, current,
                 previous);
     }
 
@@ -2566,21 +2288,13 @@
             float topAmount = getCurrentOverScrollAmount(true);
             float bottomAmount = getCurrentOverScrollAmount(false);
             if (velocityY < 0 && topAmount > 0) {
-                if (ANCHOR_SCROLLING) {
-                    mScrollAnchorViewY += topAmount;
-                } else {
-                    setOwnScrollY(mOwnScrollY - (int) topAmount);
-                }
+                setOwnScrollY(mOwnScrollY - (int) topAmount);
                 mDontReportNextOverScroll = true;
                 setOverScrollAmount(0, true, false);
                 mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
                         * mOverflingDistance + topAmount;
             } else if (velocityY > 0 && bottomAmount > 0) {
-                if (ANCHOR_SCROLLING) {
-                    mScrollAnchorViewY -= bottomAmount;
-                } else {
-                    setOwnScrollY((int) (mOwnScrollY + bottomAmount));
-                }
+                setOwnScrollY((int) (mOwnScrollY + bottomAmount));
                 setOverScrollAmount(0, false, false);
                 mMaxOverScroll = Math.abs(velocityY) / 1000f
                         * getRubberBandFactor(false /* onTop */) * mOverflingDistance
@@ -2589,139 +2303,19 @@
                 // it will be set once we reach the boundary
                 mMaxOverScroll = 0.0f;
             }
-            if (ANCHOR_SCROLLING) {
-                flingScroller(velocityY);
-            } else {
-                int scrollRange = getScrollRange();
-                int minScrollY = Math.max(0, scrollRange);
-                if (mExpandedInThisMotion) {
-                    minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
-                }
-                mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
-                        mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
+            int scrollRange = getScrollRange();
+            int minScrollY = Math.max(0, scrollRange);
+            if (mExpandedInThisMotion) {
+                minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
             }
+            mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
+                    mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
 
             animateScroll();
         }
     }
 
     /**
-     * Flings the overscroller with the given velocity (anchor-based scrolling).
-     *
-     * Because anchor-based scrolling can't track the current scroll position, the overscroller is
-     * always started at startY = 0, and we interpret the positions it computes as relative to the
-     * start of the scroll.
-     */
-    private void flingScroller(int velocityY) {
-        assert ANCHOR_SCROLLING;
-        mIsScrollerBoundSet = false;
-        maybeFlingScroller(velocityY, true /* always fling */);
-    }
-
-    private void maybeFlingScroller(int velocityY, boolean alwaysFling) {
-        assert ANCHOR_SCROLLING;
-        // Attempt to determine the maximum amount to scroll before we reach the end.
-        // If the first view is not materialized (for an upwards scroll) or the last view is either
-        // not materialized or is pinned to the shade (for a downwards scroll), we don't know this
-        // amount, so we do an unbounded fling and rely on {@link #maybeReflingScroller()} to update
-        // the scroller once we approach the start/end of the list.
-        int minY = Integer.MIN_VALUE;
-        int maxY = Integer.MAX_VALUE;
-        if (velocityY < 0) {
-            minY = getMaxNegativeScrollAmount();
-            if (minY > Integer.MIN_VALUE) {
-                mIsScrollerBoundSet = true;
-            }
-        } else {
-            maxY = getMaxPositiveScrollAmount();
-            if (maxY < Integer.MAX_VALUE) {
-                mIsScrollerBoundSet = true;
-            }
-        }
-        if (mIsScrollerBoundSet || alwaysFling) {
-            mLastScrollerY = 0;
-            // x velocity is set to 1 to avoid overscroller bug
-            mScroller.fling(0, 0, 1, velocityY, 0, 0, minY, maxY, 0,
-                    mExpandedInThisMotion
-                            && !mScrollAdapter.isScrolledToTop() ? 0 : Integer.MAX_VALUE / 2);
-        }
-    }
-
-    /**
-     * Returns the maximum number of pixels we can scroll in the positive direction (downwards)
-     * before reaching the bottom of the list (discounting overscroll).
-     *
-     * If the return value is negative then we have overscrolled; this is a transient state which
-     * should immediately be handled by adjusting the anchor position and adding the extra space to
-     * the bottom overscroll amount.
-     *
-     * If we don't know how many pixels we have left to scroll (because the last row has not been
-     * materialized, or it's in the shelf so it doesn't have its "natural" position), we return
-     * {@link Integer#MAX_VALUE}.
-     */
-    private int getMaxPositiveScrollAmount() {
-        assert ANCHOR_SCROLLING;
-        // TODO: once we're recycling we need to check the adapter position of the last child.
-        ExpandableNotificationRow lastRow = getLastRowNotGone();
-        if (mScrollAnchorView != null && lastRow != null && !lastRow.isInShelf()) {
-            // distance from bottom of last child to bottom of notifications area is:
-            // distance from bottom of last child
-            return (int) (lastRow.getTranslationY() + lastRow.getActualHeight()
-                    // to top of anchor view
-                    - mScrollAnchorView.getTranslationY()
-                    // plus distance from anchor view to top of notifications area
-                    + mScrollAnchorViewY
-                    // minus height of notifications area.
-                    - (mMaxLayoutHeight - getIntrinsicPadding() - mFooterView.getActualHeight()));
-        } else {
-            return Integer.MAX_VALUE;
-        }
-    }
-
-    /**
-     * Returns the maximum number of pixels (as a negative number) we can scroll in the negative
-     * direction (upwards) before reaching the top of the list (discounting overscroll).
-     *
-     * If the return value is positive then we have overscrolled; this is a transient state which
-     * should immediately be handled by adjusting the anchor position and adding the extra space to
-     * the top overscroll amount.
-     *
-     * If we don't know how many pixels we have left to scroll (because the first row has not been
-     * materialized), we return {@link Integer#MIN_VALUE}.
-     */
-    private int getMaxNegativeScrollAmount() {
-        assert ANCHOR_SCROLLING;
-        // TODO: once we're recycling we need to check the adapter position of the first child.
-        ExpandableView firstChild = getFirstChildNotGone();
-        if (mScrollAnchorView != null && firstChild != null) {
-            // distance from top of first child to top of notifications area is:
-            // distance from top of anchor view
-            return (int) -(mScrollAnchorView.getTranslationY()
-                    // to top of first child
-                    - firstChild.getTranslationY()
-                    // minus distance from top of anchor view to top of notifications area.
-                    - mScrollAnchorViewY);
-        } else {
-            return Integer.MIN_VALUE;
-        }
-    }
-
-    /**
-     * During a fling, if we were unable to set the bounds of the fling due to the top/bottom view
-     * not being materialized or being pinned to the shelf, we need to check on every frame if we're
-     * able to set the bounds.  If we are, we fling the scroller again with the newly computed
-     * bounds.
-     */
-    private void maybeReflingScroller() {
-        if (!mIsScrollerBoundSet) {
-            // Because mScroller is a flywheel scroller, we fling with the minimum possible
-            // velocity to establish direction, so as not to perceptibly affect the velocity.
-            maybeFlingScroller((int) Math.signum(mScroller.getCurrVelocity()),
-                    false /* alwaysFling */);
-        }
-    }
-
-    /**
      * @return Whether a fling performed on the top overscroll edge lead to the expanded
      * overScroll view (i.e QS).
      */
@@ -2990,38 +2584,17 @@
      */
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
-        if (ANCHOR_SCROLLING) {
-            if (removedChild == mScrollAnchorView) {
-                ExpandableView firstChild = getFirstChildNotGone();
-                if (firstChild != null) {
-                    mScrollAnchorView = firstChild;
-                } else {
-                    mScrollAnchorView = mShelf;
-                }
-                // Adjust anchor view Y by the distance between the old and new anchors
-                // so that there's no visible change.
-                mScrollAnchorViewY +=
-                        mScrollAnchorView.getTranslationY() - removedChild.getTranslationY();
-            }
-            updateScrollAnchor();
-            // TODO: once we're recycling this will need to check the adapter position of the child
-            if (mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY > 0) {
-                mScrollAnchorViewY = 0;
-            }
-            updateOnScrollChange();
-        } else {
-            final int startingPosition = getPositionInLinearLayout(removedChild);
-            final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements;
-            final int endPosition = startingPosition + childHeight;
-            if (endPosition <= mOwnScrollY) {
-                // This child is fully scrolled of the top, so we have to deduct its height from the
-                // scrollPosition
-                setOwnScrollY(mOwnScrollY - childHeight);
-            } else if (startingPosition < mOwnScrollY) {
-                // This child is currently being scrolled into, set the scroll position to the
-                // start of this child
-                setOwnScrollY(startingPosition);
-            }
+        final int startingPosition = getPositionInLinearLayout(removedChild);
+        final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements;
+        final int endPosition = startingPosition + childHeight;
+        if (endPosition <= mOwnScrollY) {
+            // This child is fully scrolled of the top, so we have to deduct its height from the
+            // scrollPosition
+            setOwnScrollY(mOwnScrollY - childHeight);
+        } else if (startingPosition < mOwnScrollY) {
+            // This child is currently being scrolled into, set the scroll position to the
+            // start of this child
+            setOwnScrollY(startingPosition);
         }
     }
 
@@ -3115,15 +2688,6 @@
         if (child instanceof ExpandableNotificationRow) {
             ((ExpandableNotificationRow) child).setDismissRtl(mDismissRtl);
         }
-        if (ANCHOR_SCROLLING) {
-            // TODO: once we're recycling this will need to check the adapter position of the child
-            if (child == getFirstChildNotGone()
-                    && (mScrollAdapter.isScrolledToTop() || !mIsExpanded)) {
-                // New child was added at the top while we're scrolled to the top;
-                // make it the new anchor view so that we stay at the top.
-                mScrollAnchorView = child;
-            }
-        }
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
@@ -3581,24 +3145,17 @@
                         final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
                         if (vscroll != 0) {
                             final int delta = (int) (vscroll * getVerticalScrollFactor());
-                            if (ANCHOR_SCROLLING) {
-                                mScrollAnchorViewY -= delta;
-                                updateScrollAnchor();
-                                clampScrollPosition();
-                                updateOnScrollChange();
-                            } else {
-                                final int range = getScrollRange();
-                                int oldScrollY = mOwnScrollY;
-                                int newScrollY = oldScrollY - delta;
-                                if (newScrollY < 0) {
-                                    newScrollY = 0;
-                                } else if (newScrollY > range) {
-                                    newScrollY = range;
-                                }
-                                if (newScrollY != oldScrollY) {
-                                    setOwnScrollY(newScrollY);
-                                    return true;
-                                }
+                            final int range = getScrollRange();
+                            int oldScrollY = mOwnScrollY;
+                            int newScrollY = oldScrollY - delta;
+                            if (newScrollY < 0) {
+                                newScrollY = 0;
+                            } else if (newScrollY > range) {
+                                newScrollY = range;
+                            }
+                            if (newScrollY != oldScrollY) {
+                                setOwnScrollY(newScrollY);
+                                return true;
                             }
                         }
                     }
@@ -3676,13 +3233,9 @@
                     mLastMotionY = y;
                     float scrollAmount;
                     int range;
-                    if (ANCHOR_SCROLLING) {
-                        range = 0;  // unused in the methods it's being passed to
-                    } else {
-                        range = getScrollRange();
-                        if (mExpandedInThisMotion) {
-                            range = Math.min(range, mMaxScrollAfterExpand);
-                        }
+                    range = getScrollRange();
+                    if (mExpandedInThisMotion) {
+                        range = Math.min(range, mMaxScrollAfterExpand);
                     }
                     if (deltaY < 0) {
                         scrollAmount = overScrollDown(deltaY);
@@ -3727,13 +3280,9 @@
                                     onOverScrollFling(false, initialVelocity);
                                 }
                             } else {
-                                if (ANCHOR_SCROLLING) {
-                                    // TODO
-                                } else {
-                                    if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
-                                            getScrollRange())) {
-                                        animateScroll();
-                                    }
+                                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+                                        getScrollRange())) {
+                                    animateScroll();
                                 }
                             }
                         }
@@ -3745,13 +3294,9 @@
                 break;
             case MotionEvent.ACTION_CANCEL:
                 if (mIsBeingDragged && getChildCount() > 0) {
-                    if (ANCHOR_SCROLLING) {
-                        // TODO
-                    } else {
-                        if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
-                                getScrollRange())) {
-                            animateScroll();
-                        }
+                    if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+                            getScrollRange())) {
+                        animateScroll();
                     }
                     mActivePointerId = INVALID_POINTER;
                     endDrag();
@@ -3970,12 +3515,8 @@
                 setIsBeingDragged(false);
                 mActivePointerId = INVALID_POINTER;
                 recycleVelocityTracker();
-                if (ANCHOR_SCROLLING) {
-                    // TODO
-                } else {
-                    if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
-                        animateScroll();
-                    }
+                if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+                    animateScroll();
                 }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
@@ -4050,20 +3591,16 @@
             case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
                 // fall through
             case android.R.id.accessibilityActionScrollUp:
-                if (ANCHOR_SCROLLING) {
-                    // TODO
-                } else {
-                    final int viewportHeight =
-                            getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
-                                    - mShelf.getIntrinsicHeight();
-                    final int targetScrollY = Math.max(0,
-                            Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
-                    if (targetScrollY != mOwnScrollY) {
-                        mScroller.startScroll(mScrollX, mOwnScrollY, 0,
-                                targetScrollY - mOwnScrollY);
-                        animateScroll();
-                        return true;
-                    }
+                final int viewportHeight =
+                        getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
+                                - mShelf.getIntrinsicHeight();
+                final int targetScrollY = Math.max(0,
+                        Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
+                if (targetScrollY != mOwnScrollY) {
+                    mScroller.startScroll(mScrollX, mOwnScrollY, 0,
+                            targetScrollY - mOwnScrollY);
+                    animateScroll();
+                    return true;
                 }
                 break;
         }
@@ -4166,14 +3703,7 @@
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     void resetScrollPosition() {
         mScroller.abortAnimation();
-        if (ANCHOR_SCROLLING) {
-            // TODO: once we're recycling this will need to modify the adapter position instead
-            mScrollAnchorView = getFirstChildNotGone();
-            mScrollAnchorViewY = 0;
-            updateOnScrollChange();
-        } else {
-            setOwnScrollY(0);
-        }
+        setOwnScrollY(0);
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
@@ -4262,13 +3792,7 @@
                     layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
                 }
                 if (endPosition > layoutEnd) {
-                    if (ANCHOR_SCROLLING) {
-                        mScrollAnchorViewY -= (endPosition - layoutEnd);
-                        updateScrollAnchor();
-                        updateOnScrollChange();
-                    } else {
-                        setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
-                    }
+                    setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
                     mDisallowScrollingInThisMotion = true;
                 }
             }
@@ -4765,12 +4289,8 @@
         super.onInitializeAccessibilityEventInternal(event);
         event.setScrollable(mScrollable);
         event.setMaxScrollX(mScrollX);
-        if (ANCHOR_SCROLLING) {
-            // TODO
-        } else {
-            event.setScrollY(mOwnScrollY);
-            event.setMaxScrollY(getScrollRange());
-        }
+        event.setScrollY(mOwnScrollY);
+        event.setMaxScrollY(getScrollRange());
     }
 
     @Override
@@ -4955,7 +4475,6 @@
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void setOwnScrollY(int ownScrollY) {
-        assert !ANCHOR_SCROLLING;
         if (ownScrollY != mOwnScrollY) {
             // We still want to call the normal scrolled changed for accessibility reasons
             onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY);
@@ -4969,51 +4488,6 @@
         requestChildrenUpdate();
     }
 
-    private void updateScrollAnchor() {
-        int anchorIndex = indexOfChild(mScrollAnchorView);
-        // If the anchor view has been scrolled off the top, move to the next view.
-        while (mScrollAnchorViewY < 0) {
-            View nextAnchor = null;
-            for (int i = anchorIndex + 1; i < getChildCount(); i++) {
-                View child = getChildAt(i);
-                if (child.getVisibility() != View.GONE
-                        && child instanceof ExpandableNotificationRow) {
-                    anchorIndex = i;
-                    nextAnchor = child;
-                    break;
-                }
-            }
-            if (nextAnchor == null) {
-                break;
-            }
-            mScrollAnchorViewY +=
-                    (int) (nextAnchor.getTranslationY() - mScrollAnchorView.getTranslationY());
-            mScrollAnchorView = nextAnchor;
-        }
-        // If the view above the anchor view is fully visible, make it the anchor view.
-        while (anchorIndex > 0 && mScrollAnchorViewY > 0) {
-            View prevAnchor = null;
-            for (int i = anchorIndex - 1; i >= 0; i--) {
-                View child = getChildAt(i);
-                if (child.getVisibility() != View.GONE
-                        && child instanceof ExpandableNotificationRow) {
-                    anchorIndex = i;
-                    prevAnchor = child;
-                    break;
-                }
-            }
-            if (prevAnchor == null) {
-                break;
-            }
-            float distanceToPreviousAnchor =
-                    mScrollAnchorView.getTranslationY() - prevAnchor.getTranslationY();
-            if (distanceToPreviousAnchor < mScrollAnchorViewY) {
-                mScrollAnchorViewY -= (int) distanceToPreviousAnchor;
-                mScrollAnchorView = prevAnchor;
-            }
-        }
-    }
-
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void setShelfController(NotificationShelfController notificationShelfController) {
         int index = -1;
@@ -5026,9 +4500,6 @@
         mAmbientState.setShelf(mShelf);
         mStateAnimator.setShelf(mShelf);
         notificationShelfController.bind(mAmbientState, mController);
-        if (ANCHOR_SCROLLING) {
-            mScrollAnchorView = mShelf;
-        }
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5496,7 +4967,13 @@
         mSwipedOutViews.add(v);
     }
 
-    void onSwipeBegin() {
+    void onSwipeBegin(View v) {
+        if (v instanceof ExpandableView) {
+            ExpandableView ev = (ExpandableView) v;
+            ev.setIsBeingSwiped(true);
+            mController.getNoticationRoundessManager()
+                    .updateViewWithoutCallback(ev, true /* animate */);
+        }
         requestDisallowInterceptTouchEvent(true);
         updateFirstAndLastBackgroundViews();
         updateContinuousShadowDrawing();
@@ -5504,7 +4981,13 @@
         requestChildrenUpdate();
     }
 
-    void onSwipeEnd() {
+    void onSwipeEnd(View v) {
+        if (v instanceof ExpandableView) {
+            ExpandableView ev = (ExpandableView) v;
+            ev.setIsBeingSwiped(false);
+            mController.getNoticationRoundessManager()
+                    .updateViewWithoutCallback(ev, true /* animate */);
+        }
         updateFirstAndLastBackgroundViews();
     }
 
@@ -5631,15 +5114,7 @@
         mSectionsManager.updateSectionBoundaries(reason);
     }
 
-    boolean isSilkDismissEnabled() {
-        return Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* enabled by default */) == 1;
-    }
-
     void updateContinuousBackgroundDrawing() {
-        if (isSilkDismissEnabled()) {
-            return;
-        }
         boolean continuousBackground = !mAmbientState.isFullyAwake()
                 && mSwipeHelper.isSwiping();
         if (continuousBackground != mContinuousBackgroundUpdate) {
@@ -6166,11 +5641,7 @@
         public void expansionStateChanged(boolean isExpanding) {
             mExpandingNotification = isExpanding;
             if (!mExpandedInThisMotion) {
-                if (ANCHOR_SCROLLING) {
-                    // TODO
-                } else {
-                    mMaxScrollAfterExpand = mOwnScrollY;
-                }
+                mMaxScrollAfterExpand = mOwnScrollY;
                 mExpandedInThisMotion = true;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index c2d030b..e332f18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -395,7 +395,7 @@
                     if (mView.getDismissAllInProgress()) {
                         return;
                     }
-                    mView.onSwipeEnd();
+                    mView.onSwipeEnd(view);
                     if (view instanceof ExpandableNotificationRow) {
                         ExpandableNotificationRow row = (ExpandableNotificationRow) view;
                         if (row.isHeadsUp()) {
@@ -450,12 +450,12 @@
                 @Override
                 public void onBeginDrag(View v) {
                     mFalsingCollector.onNotificationStartDismissing();
-                    mView.onSwipeBegin();
+                    mView.onSwipeBegin(v);
                 }
 
                 @Override
                 public void onChildSnappedBack(View animView, float targetLeft) {
-                    mView.onSwipeEnd();
+                    mView.onSwipeEnd(animView);
                     if (animView instanceof ExpandableNotificationRow) {
                         ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
                         if (row.isPinned() && !canChildBeDismissed(row)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index d85baa9..2c206b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -45,8 +45,6 @@
  */
 public class StackScrollAlgorithm {
 
-    static final boolean ANCHOR_SCROLLING = false;
-
     private static final String LOG_TAG = "StackScrollAlgorithm";
     private final ViewGroup mHostView;
 
@@ -229,10 +227,6 @@
         scrollY = Math.max(0, scrollY);
         state.scrollY = (int) (scrollY + bottomOverScroll);
 
-        if (ANCHOR_SCROLLING) {
-            state.anchorViewY = (int) (ambientState.getAnchorViewY() - bottomOverScroll);
-        }
-
         //now init the visible children and update paddings
         int childCount = hostView.getChildCount();
         state.visibleChildren.clear();
@@ -240,11 +234,6 @@
         int notGoneIndex = 0;
         ExpandableView lastView = null;
         for (int i = 0; i < childCount; i++) {
-            if (ANCHOR_SCROLLING) {
-                if (i == ambientState.getAnchorViewIndex()) {
-                    state.anchorViewIndex = state.visibleChildren.size();
-                }
-            }
             ExpandableView v = (ExpandableView) hostView.getChildAt(i);
             if (v.getVisibility() != View.GONE) {
                 if (v == ambientState.getShelf()) {
@@ -293,26 +282,12 @@
      */
     private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
             AmbientState ambientState) {
-        if (ANCHOR_SCROLLING) {
-            float currentYPosition = algorithmState.anchorViewY;
-            int childCount = algorithmState.visibleChildren.size();
-            for (int i = algorithmState.anchorViewIndex; i < childCount; i++) {
-                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
-                        false /* reverse */);
-            }
-            currentYPosition = algorithmState.anchorViewY;
-            for (int i = algorithmState.anchorViewIndex - 1; i >= 0; i--) {
-                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
-                        true /* reverse */);
-            }
-        } else {
-            // The y coordinate of the current child.
-            float currentYPosition = -algorithmState.scrollY;
-            int childCount = algorithmState.visibleChildren.size();
-            for (int i = 0; i < childCount; i++) {
-                currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
-                        false /* reverse */);
-            }
+        // The y coordinate of the current child.
+        float currentYPosition = -algorithmState.scrollY;
+        int childCount = algorithmState.visibleChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
+                    false /* reverse */);
         }
     }
 
@@ -343,7 +318,7 @@
         ExpandableView previousChild = i > 0 ? algorithmState.visibleChildren.get(i - 1) : null;
         final boolean applyGapHeight =
                 childNeedsGapHeight(
-                        ambientState.getSectionProvider(), algorithmState.anchorViewIndex, i,
+                        ambientState.getSectionProvider(), i,
                         child, previousChild);
         ExpandableViewState childViewState = child.getViewState();
         childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
@@ -409,7 +384,6 @@
      * Get the gap height needed for before a view
      *
      * @param sectionProvider the sectionProvider used to understand the sections
-     * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not
      * @param visibleIndex the visible index of this view in the list
      * @param child the child asked about
      * @param previousChild the child right before it or null if none
@@ -417,12 +391,11 @@
      */
     public float getGapHeightForChild(
             SectionProvider sectionProvider,
-            int anchorViewIndex,
             int visibleIndex,
             View child,
             View previousChild) {
 
-        if (childNeedsGapHeight(sectionProvider, anchorViewIndex, visibleIndex, child,
+        if (childNeedsGapHeight(sectionProvider, visibleIndex, child,
                 previousChild)) {
             return mGapHeight;
         } else {
@@ -434,7 +407,6 @@
      * Does a given child need a gap, i.e spacing before a view?
      *
      * @param sectionProvider the sectionProvider used to understand the sections
-     * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not
      * @param visibleIndex the visible index of this view in the list
      * @param child the child asked about
      * @param previousChild the child right before it or null if none
@@ -442,16 +414,12 @@
      */
     private boolean childNeedsGapHeight(
             SectionProvider sectionProvider,
-            int anchorViewIndex,
             int visibleIndex,
             View child,
             View previousChild) {
 
         boolean needsGapHeight = sectionProvider.beginsSection(child, previousChild)
                 && visibleIndex > 0;
-        if (ANCHOR_SCROLLING) {
-            needsGapHeight &= visibleIndex != anchorViewIndex;
-        }
         return needsGapHeight;
     }
 
@@ -537,7 +505,6 @@
                 // To check if the row need to do translation according to scroll Y
                 // heads up show full of row's content and any scroll y indicate that the
                 // translationY need to move up the HUN.
-                // TODO: fix this check for anchor scrolling.
                 if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
                     childState.yTranslation -= ambientState.getScrollY();
                 }
@@ -701,14 +668,6 @@
          */
         public int scrollY;
 
-        /** The index of the anchor view (anchor scrolling). */
-        public int anchorViewIndex;
-
-        /**
-         * The Y position, relative to the top of the screen, of the anchor view (anchor scrolling).
-         */
-        public int anchorViewY;
-
         /**
          * The children from the host view which are not gone.
          */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index d4add95..66a48f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -42,6 +42,7 @@
 public class StackStateAnimator {
 
     public static final int ANIMATION_DURATION_STANDARD = 360;
+    public static final int ANIMATION_DURATION_CORNER_RADIUS = 200;
     public static final int ANIMATION_DURATION_WAKEUP = 500;
     public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
     public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 9ea402d..d074e64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -652,7 +652,7 @@
         pw.println(TAG + ":");
         pw.println("  mKeyguardDisplayMode=" + mKeyguardDisplayMode);
         pw.println(mCurrentState);
-        mNotificationShadeView.getViewRootImpl().dump("  ", fd, pw, args);
+        mNotificationShadeView.getViewRootImpl().dump("  ", pw);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9ebde53..a18d87c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -234,7 +234,7 @@
 import com.android.systemui.volume.VolumeComponent;
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -394,7 +394,7 @@
     private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
     private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder;
     private final PluginManager mPluginManager;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     private final StatusBarNotificationActivityStarter.Builder
             mStatusBarNotificationActivityStarterBuilder;
     private final ShadeController mShadeController;
@@ -738,7 +738,7 @@
             CommandQueue commandQueue,
             Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
             PluginManager pluginManager,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             LightsOutNotifController lightsOutNotifController,
             StatusBarNotificationActivityStarter.Builder
                     statusBarNotificationActivityStarterBuilder,
@@ -1568,14 +1568,14 @@
             return false;
         }
 
-        final SplitScreen splitScreen = mSplitScreenOptional.get();
-        if (splitScreen.isDividerVisible()) {
-            if (splitScreen.isMinimized() && !splitScreen.isHomeStackResizable()) {
+        final LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get();
+        if (legacySplitScreen.isDividerVisible()) {
+            if (legacySplitScreen.isMinimized() && !legacySplitScreen.isHomeStackResizable()) {
                 // Undocking from the minimized state is not supported
                 return false;
             }
 
-            splitScreen.onUndockingTask();
+            legacySplitScreen.onUndockingTask();
             if (metricsUndockAction != -1) {
                 mMetricsLogger.action(metricsUndockAction);
             }
@@ -1587,7 +1587,7 @@
             return false;
         }
 
-        if (splitScreen.splitPrimaryTask()) {
+        if (legacySplitScreen.splitPrimaryTask()) {
             if (metricsDockAction != -1) {
                 mMetricsLogger.action(metricsDockAction);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 2aa3f37..26e1959 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -100,7 +100,7 @@
 import com.android.systemui.volume.VolumeComponent;
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -181,7 +181,7 @@
             CommandQueue commandQueue,
             Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
             PluginManager pluginManager,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             LightsOutNotifController lightsOutNotifController,
             StatusBarNotificationActivityStarter.Builder
                     statusBarNotificationActivityStarterBuilder,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
deleted file mode 100644
index 8f86e2d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.systemui.R;
-
-/**
- * Content descriptions for accessibility support.
- */
-public class AccessibilityContentDescriptions {
-
-    private AccessibilityContentDescriptions() {}
-    static final int[] PHONE_SIGNAL_STRENGTH = {
-        R.string.accessibility_no_phone,
-        R.string.accessibility_phone_one_bar,
-        R.string.accessibility_phone_two_bars,
-        R.string.accessibility_phone_three_bars,
-        R.string.accessibility_phone_signal_full
-    };
-
-    static final int[] DATA_CONNECTION_STRENGTH = {
-        R.string.accessibility_no_data,
-        R.string.accessibility_data_one_bar,
-        R.string.accessibility_data_two_bars,
-        R.string.accessibility_data_three_bars,
-        R.string.accessibility_data_signal_full
-    };
-
-    static final int[] WIFI_CONNECTION_STRENGTH = {
-        R.string.accessibility_no_wifi,
-        R.string.accessibility_wifi_one_bar,
-        R.string.accessibility_wifi_two_bars,
-        R.string.accessibility_wifi_three_bars,
-        R.string.accessibility_wifi_signal_full
-    };
-
-    static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
-
-    static final int[] ETHERNET_CONNECTION_VALUES = {
-        R.string.accessibility_ethernet_disconnected,
-        R.string.accessibility_ethernet_connected,
-    };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index 4fbf5ff..2eff04e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -18,6 +18,9 @@
 import android.content.Context;
 import android.net.NetworkCapabilities;
 
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
@@ -25,7 +28,7 @@
 
 
 public class EthernetSignalController extends
-        SignalController<SignalController.State, SignalController.IconGroup> {
+        SignalController<State, IconGroup> {
 
     public EthernetSignalController(Context context,
             CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
@@ -57,7 +60,7 @@
     }
 
     @Override
-    public SignalController.State cleanState() {
-        return new SignalController.State();
+    public State cleanState() {
+        return new State();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index dd9165d..947b9182 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -15,9 +15,9 @@
  */
 package com.android.systemui.statusbar.policy;
 
+import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons;
 import static com.android.settingslib.mobile.MobileMappings.getIconKey;
-import static com.android.settingslib.mobile.MobileMappings.toDisplayIconKey;
-import static com.android.settingslib.mobile.MobileMappings.toIconKey;
+import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
 
 import android.content.Context;
 import android.content.Intent;
@@ -39,25 +39,28 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
+import com.android.settingslib.SignalIcon.MobileState;
 import com.android.settingslib.Utils;
 import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.MobileMappings.Config;
 import com.android.settingslib.mobile.MobileStatusTracker;
 import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
-public class MobileSignalController extends SignalController<
-        MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
+/**
+ * Monitors the mobile signal changes and update the SysUI icons.
+ */
+public class MobileSignalController extends SignalController<MobileState, MobileIconGroup> {
     private final TelephonyManager mPhone;
     private final SubscriptionDefaults mDefaults;
     private final String mNetworkNameDefault;
@@ -66,7 +69,8 @@
     // Save entire info for logging, we only use the id.
     final SubscriptionInfo mSubscriptionInfo;
     // @VisibleForDemoMode
-    final Map<String, MobileIconGroup> mNetworkToIconLookup;
+    Map<String, MobileIconGroup> mNetworkToIconLookup;
+
     // Since some pieces of the phone state are interdependent we store it locally,
     // this could potentially become part of MobileState for simplification/complication
     // of code.
@@ -93,7 +97,6 @@
         super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
                 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
                 networkController);
-        mNetworkToIconLookup = new HashMap<>();
         mConfig = config;
         mPhone = phone;
         mDefaults = defaults;
@@ -102,7 +105,10 @@
                 .toString();
         mNetworkNameDefault = getTextIfExists(
                 com.android.internal.R.string.lockscreen_carrier_default).toString();
-        mapIconSets();
+
+        mNetworkToIconLookup = mapIconSets(mConfig);
+        mDefaultIcons = getDefaultIcons(mConfig);
+
         String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
                 : mNetworkNameDefault;
         mLastState.networkName = mCurrentState.networkName = networkName;
@@ -139,7 +145,8 @@
     public void setConfiguration(Config config) {
         mConfig = config;
         updateInflateSignalStrength();
-        mapIconSets();
+        mNetworkToIconLookup = mapIconSets(mConfig);
+        mDefaultIcons = getDefaultIcons(mConfig);
         updateTelephony();
     }
 
@@ -187,113 +194,6 @@
         mContext.getContentResolver().unregisterContentObserver(mObserver);
     }
 
-    /**
-     * Produce a mapping of data network types to icon groups for simple and quick use in
-     * updateTelephony.
-     */
-    private void mapIconSets() {
-        mNetworkToIconLookup.clear();
-
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0),
-                TelephonyIcons.THREE_G);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A),
-                TelephonyIcons.THREE_G);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B),
-                TelephonyIcons.THREE_G);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD),
-                TelephonyIcons.THREE_G);
-        if (mConfig.show4gFor3g) {
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
-                TelephonyIcons.FOUR_G);
-        } else {
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
-                TelephonyIcons.THREE_G);
-        }
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA),
-                TelephonyIcons.THREE_G);
-
-        if (!mConfig.showAtLeast3G) {
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
-                    TelephonyIcons.UNKNOWN);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
-                    TelephonyIcons.E);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
-                    TelephonyIcons.ONE_X);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
-                    TelephonyIcons.ONE_X);
-
-            mDefaultIcons = TelephonyIcons.G;
-        } else {
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
-                    TelephonyIcons.THREE_G);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
-                    TelephonyIcons.THREE_G);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
-                    TelephonyIcons.THREE_G);
-            mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
-                    TelephonyIcons.THREE_G);
-            mDefaultIcons = TelephonyIcons.THREE_G;
-        }
-
-        MobileIconGroup hGroup = TelephonyIcons.THREE_G;
-        MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
-        if (mConfig.show4gFor3g) {
-            hGroup = TelephonyIcons.FOUR_G;
-            hPlusGroup = TelephonyIcons.FOUR_G;
-        } else if (mConfig.hspaDataDistinguishable) {
-            hGroup = TelephonyIcons.H;
-            hPlusGroup = TelephonyIcons.H_PLUS;
-        }
-
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup);
-        mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup);
-
-        if (mConfig.show4gForLte) {
-            mNetworkToIconLookup.put(toIconKey(
-                    TelephonyManager.NETWORK_TYPE_LTE),
-                    TelephonyIcons.FOUR_G);
-            if (mConfig.hideLtePlus) {
-                mNetworkToIconLookup.put(toDisplayIconKey(
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
-                        TelephonyIcons.FOUR_G);
-            } else {
-                mNetworkToIconLookup.put(toDisplayIconKey(
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
-                        TelephonyIcons.FOUR_G_PLUS);
-            }
-        } else {
-            mNetworkToIconLookup.put(toIconKey(
-                    TelephonyManager.NETWORK_TYPE_LTE),
-                    TelephonyIcons.LTE);
-            if (mConfig.hideLtePlus) {
-                mNetworkToIconLookup.put(toDisplayIconKey(
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
-                        TelephonyIcons.LTE);
-            } else {
-                mNetworkToIconLookup.put(toDisplayIconKey(
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
-                        TelephonyIcons.LTE_PLUS);
-            }
-        }
-        mNetworkToIconLookup.put(toIconKey(
-                TelephonyManager.NETWORK_TYPE_IWLAN),
-                TelephonyIcons.WFC);
-        mNetworkToIconLookup.put(toDisplayIconKey(
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
-                TelephonyIcons.LTE_CA_5G_E);
-        mNetworkToIconLookup.put(toDisplayIconKey(
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
-                TelephonyIcons.NR_5G);
-        mNetworkToIconLookup.put(toDisplayIconKey(
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE),
-                TelephonyIcons.NR_5G_PLUS);
-        mNetworkToIconLookup.put(toIconKey(
-                TelephonyManager.NETWORK_TYPE_NR),
-                TelephonyIcons.NR_5G);
-    }
-
     private void updateInflateSignalStrength() {
         mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
                 mSubscriptionInfo.getSubscriptionId());
@@ -339,7 +239,7 @@
         MobileIconGroup icons = getIcons();
 
         String contentDescription = getTextIfExists(getContentDescription()).toString();
-        CharSequence dataContentDescriptionHtml = getTextIfExists(icons.mDataContentDescription);
+        CharSequence dataContentDescriptionHtml = getTextIfExists(icons.dataContentDescription);
 
         //TODO: Hacky
         // The data content description can sometimes be shown in a text view and might come to us
@@ -363,7 +263,7 @@
         CharSequence description = null;
         // Only send data sim callbacks to QS.
         if (mCurrentState.dataSim) {
-            qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0;
+            qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
             qsIcon = new IconState(mCurrentState.enabled
                     && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
             description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
@@ -375,10 +275,10 @@
                 && !mCurrentState.carrierNetworkChangeMode
                 && mCurrentState.activityOut;
         showDataIcon &= mCurrentState.isDefault || dataDisabled;
-        int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0;
+        int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
         callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
-                description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(),
+                description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
                 mCurrentState.roaming);
     }
 
@@ -610,87 +510,4 @@
         pw.println("  mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
         pw.println("  isDataDisabled=" + isDataDisabled() + ",");
     }
-
-    static class MobileIconGroup extends SignalController.IconGroup {
-        final int mDataContentDescription; // mContentDescriptionDataType
-        final int mDataType;
-        final boolean mIsWide;
-        final int mQsDataType;
-
-        public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
-                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
-                int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
-            super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
-                    qsDiscState, discContentDesc);
-            mDataContentDescription = dataContentDesc;
-            mDataType = dataType;
-            mIsWide = isWide;
-            mQsDataType = dataType; // TODO: remove this field
-        }
-    }
-
-    static class MobileState extends SignalController.State {
-        String networkName;
-        String networkNameData;
-        boolean dataSim;
-        boolean dataConnected;
-        boolean isEmergency;
-        boolean airplaneMode;
-        boolean carrierNetworkChangeMode;
-        boolean isDefault;
-        boolean userSetup;
-        boolean roaming;
-        boolean defaultDataOff;  // Tracks the on/off state of the defaultDataSubscription
-
-        @Override
-        public void copyFrom(State s) {
-            super.copyFrom(s);
-            MobileState state = (MobileState) s;
-            dataSim = state.dataSim;
-            networkName = state.networkName;
-            networkNameData = state.networkNameData;
-            dataConnected = state.dataConnected;
-            isDefault = state.isDefault;
-            isEmergency = state.isEmergency;
-            airplaneMode = state.airplaneMode;
-            carrierNetworkChangeMode = state.carrierNetworkChangeMode;
-            userSetup = state.userSetup;
-            roaming = state.roaming;
-            defaultDataOff = state.defaultDataOff;
-        }
-
-        @Override
-        protected void toString(StringBuilder builder) {
-            super.toString(builder);
-            builder.append(',');
-            builder.append("dataSim=").append(dataSim).append(',');
-            builder.append("networkName=").append(networkName).append(',');
-            builder.append("networkNameData=").append(networkNameData).append(',');
-            builder.append("dataConnected=").append(dataConnected).append(',');
-            builder.append("roaming=").append(roaming).append(',');
-            builder.append("isDefault=").append(isDefault).append(',');
-            builder.append("isEmergency=").append(isEmergency).append(',');
-            builder.append("airplaneMode=").append(airplaneMode).append(',');
-            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
-                    .append(',');
-            builder.append("userSetup=").append(userSetup).append(',');
-            builder.append("defaultDataOff=").append(defaultDataOff);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return super.equals(o)
-                    && Objects.equals(((MobileState) o).networkName, networkName)
-                    && Objects.equals(((MobileState) o).networkNameData, networkNameData)
-                    && ((MobileState) o).dataSim == dataSim
-                    && ((MobileState) o).dataConnected == dataConnected
-                    && ((MobileState) o).isEmergency == isEmergency
-                    && ((MobileState) o).airplaneMode == airplaneMode
-                    && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
-                    && ((MobileState) o).userSetup == userSetup
-                    && ((MobileState) o).isDefault == isDefault
-                    && ((MobileState) o).roaming == roaming
-                    && ((MobileState) o).defaultDataOff == defaultDataOff;
-        }
-    }
 }
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 a3abb31..0ca2b4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -30,7 +30,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -40,7 +39,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.PersistableBundle;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellSignalStrength;
@@ -59,7 +57,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.mobile.MobileMappings.Config;
 import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
@@ -1201,45 +1201,4 @@
             registerListeners();
         }
     };
-
-    @VisibleForTesting
-    static class Config {
-        boolean showAtLeast3G = false;
-        boolean show4gFor3g = false;
-        boolean alwaysShowCdmaRssi = false;
-        boolean show4gForLte = false;
-        boolean hideLtePlus = false;
-        boolean hspaDataDistinguishable;
-        boolean alwaysShowDataRatIcon = false;
-
-        static Config readConfig(Context context) {
-            Config config = new Config();
-            Resources res = context.getResources();
-
-            config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
-            config.alwaysShowCdmaRssi =
-                    res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
-            config.hspaDataDistinguishable =
-                    res.getBoolean(R.bool.config_hspa_data_distinguishable);
-
-            CarrierConfigManager configMgr = (CarrierConfigManager)
-                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-            // Handle specific carrier config values for the default data SIM
-            int defaultDataSubId = SubscriptionManager.from(context)
-                    .getDefaultDataSubscriptionId();
-            PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
-            if (b != null) {
-                config.alwaysShowDataRatIcon = b.getBoolean(
-                        CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
-                config.show4gForLte = b.getBoolean(
-                        CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
-                config.show4gFor3g = b.getBoolean(
-                        CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
-                config.hideLtePlus = b.getBoolean(
-                        CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
-            }
-
-            return config;
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 3a45691..a05fe1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -21,18 +21,21 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
 import java.util.BitSet;
 
 
 /**
  * Common base class for handling signal for both wifi and mobile data.
+ *
+ * @param <T> State of the SysUI controller.
+ * @param <I> Icon groups of the SysUI controller for a given State.
  */
-public abstract class SignalController<T extends SignalController.State,
-        I extends SignalController.IconGroup> {
+public abstract class SignalController<T extends State, I extends IconGroup> {
     // Save the previous SignalController.States of all SignalControllers for dumps.
     static final boolean RECORD_HISTORY = true;
     // If RECORD_HISTORY how many to save, must be a power of 2.
@@ -124,11 +127,11 @@
      */
     public int getQsCurrentIconId() {
         if (mCurrentState.connected) {
-            return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level];
+            return getIcons().qsIcons[mCurrentState.inetCondition][mCurrentState.level];
         } else if (mCurrentState.enabled) {
-            return getIcons().mQsDiscState;
+            return getIcons().qsDiscState;
         } else {
-            return getIcons().mQsNullState;
+            return getIcons().qsNullState;
         }
     }
 
@@ -137,11 +140,11 @@
      */
     public int getCurrentIconId() {
         if (mCurrentState.connected) {
-            return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level];
+            return getIcons().sbIcons[mCurrentState.inetCondition][mCurrentState.level];
         } else if (mCurrentState.enabled) {
-            return getIcons().mSbDiscState;
+            return getIcons().sbDiscState;
         } else {
-            return getIcons().mSbNullState;
+            return getIcons().sbNullState;
         }
     }
 
@@ -151,9 +154,9 @@
      */
     public int getContentDescription() {
         if (mCurrentState.connected) {
-            return getIcons().mContentDesc[mCurrentState.level];
+            return getIcons().contentDesc[mCurrentState.level];
         } else {
-            return getIcons().mDiscContentDesc;
+            return getIcons().discContentDesc;
         }
     }
 
@@ -216,108 +219,4 @@
      * Generate a blank T.
      */
     protected abstract T cleanState();
-
-    /*
-     * Holds icons for a given state. Arrays are generally indexed as inet
-     * state (full connectivity or not) first, and second dimension as
-     * signal strength.
-     */
-    static class IconGroup {
-        final int[][] mSbIcons;
-        final int[][] mQsIcons;
-        final int[] mContentDesc;
-        final int mSbNullState;
-        final int mQsNullState;
-        final int mSbDiscState;
-        final int mQsDiscState;
-        final int mDiscContentDesc;
-        // For logging.
-        final String mName;
-
-        public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
-                int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
-                int discContentDesc) {
-            mName = name;
-            mSbIcons = sbIcons;
-            mQsIcons = qsIcons;
-            mContentDesc = contentDesc;
-            mSbNullState = sbNullState;
-            mQsNullState = qsNullState;
-            mSbDiscState = sbDiscState;
-            mQsDiscState = qsDiscState;
-            mDiscContentDesc = discContentDesc;
-        }
-
-        @Override
-        public String toString() {
-            return "IconGroup(" + mName + ")";
-        }
-    }
-
-    static class State {
-        // No locale as it's only used for logging purposes
-        private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
-        boolean connected;
-        boolean enabled;
-        boolean activityIn;
-        boolean activityOut;
-        int level;
-        IconGroup iconGroup;
-        int inetCondition;
-        int rssi; // Only for logging.
-
-        // Not used for comparison, just used for logging.
-        long time;
-
-        public void copyFrom(State state) {
-            connected = state.connected;
-            enabled = state.enabled;
-            level = state.level;
-            iconGroup = state.iconGroup;
-            inetCondition = state.inetCondition;
-            activityIn = state.activityIn;
-            activityOut = state.activityOut;
-            rssi = state.rssi;
-            time = state.time;
-        }
-
-        @Override
-        public String toString() {
-            if (time != 0) {
-                StringBuilder builder = new StringBuilder();
-                toString(builder);
-                return builder.toString();
-            } else {
-                return "Empty " + getClass().getSimpleName();
-            }
-        }
-
-        protected void toString(StringBuilder builder) {
-            builder.append("connected=").append(connected).append(',')
-                    .append("enabled=").append(enabled).append(',')
-                    .append("level=").append(level).append(',')
-                    .append("inetCondition=").append(inetCondition).append(',')
-                    .append("iconGroup=").append(iconGroup).append(',')
-                    .append("activityIn=").append(activityIn).append(',')
-                    .append("activityOut=").append(activityOut).append(',')
-                    .append("rssi=").append(rssi).append(',')
-                    .append("lastModified=").append(sSDF.format(time));
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (!o.getClass().equals(getClass())) {
-                return false;
-            }
-            State other = (State) o;
-            return other.connected == connected
-                    && other.enabled == enabled
-                    && other.level == level
-                    && other.inetCondition == inetCondition
-                    && other.iconGroup == iconGroup
-                    && other.activityIn == activityIn
-                    && other.activityOut == activityOut
-                    && other.rssi == rssi;
-        }
-    }
 }
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 4ae9665..82ce4c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,9 @@
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -36,7 +39,7 @@
 import java.util.Objects;
 
 public class WifiSignalController extends
-        SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
+        SignalController<WifiSignalController.WifiState, IconGroup> {
     private final boolean mHasMobileDataFeature;
     private final WifiStatusTracker mWifiTracker;
 
@@ -156,7 +159,7 @@
         }
     }
 
-    static class WifiState extends SignalController.State {
+    static class WifiState extends State {
         String ssid;
         boolean isTransient;
         boolean isDefault;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 50cef78..e357577 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -17,6 +17,7 @@
 
 import android.content.om.OverlayInfo;
 import android.content.om.OverlayManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -49,6 +50,8 @@
 public class ThemeOverlayApplier implements Dumpable {
     private static final String TAG = "ThemeOverlayApplier";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean MONET_ENABLED = SystemProperties
+            .getBoolean("persist.sysui.monet", false);
 
     @VisibleForTesting
     static final String MONET_ACCENT_COLOR_PACKAGE = "com.android.theme.accentcolor.color";
@@ -178,6 +181,9 @@
     }
 
     private void collectMonetSystemOverlays() {
+        if (!MONET_ENABLED) {
+            return;
+        }
         List<OverlayInfo> androidOverlays = mOverlayManager
                 .getOverlayInfosForTarget(ANDROID_PACKAGE, UserHandle.SYSTEM);
         for (OverlayInfo overlayInfo : androidOverlays) {
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 006ecb9..a287e57 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -98,9 +98,9 @@
     private WallpaperColors mLockColors;
     private WallpaperColors mSystemColors;
     // Color extracted from wallpaper, NOT the color used on the overlay
-    private int mMainWallpaperColor = Color.TRANSPARENT;
+    protected int mMainWallpaperColor = Color.TRANSPARENT;
     // Color extracted from wallpaper, NOT the color used on the overlay
-    private int mWallpaperAccentColor = Color.TRANSPARENT;
+    protected int mWallpaperAccentColor = Color.TRANSPARENT;
     // Main system color that maps to an overlay color
     private int mSystemOverlayColor = Color.TRANSPARENT;
     // Accent color that maps to an overlay color
@@ -200,31 +200,26 @@
     }
 
     private void reevaluateSystemTheme() {
-        if (mLockColors == null && mSystemColors == null) {
-            Log.w(TAG, "Cannot update theme, colors are null");
-            return;
-        }
-        WallpaperColors currentColor =
+        WallpaperColors currentColors =
                 mKeyguardStateController.isShowing() && mLockColors != null
                         ? mLockColors : mSystemColors;
-        int mainColor = currentColor.getPrimaryColor().toArgb();
 
-        //TODO(b/172860591) implement more complex logic for picking accent color.
-        //For now, picking the secondary should be enough.
-        Color accentCandidate = currentColor.getSecondaryColor();
-        if (accentCandidate == null) {
-            accentCandidate = currentColor.getTertiaryColor();
-        }
-        if (accentCandidate == null) {
-            accentCandidate = currentColor.getPrimaryColor();
+        final int mainColor;
+        final int accentCandidate;
+        if (currentColors == null) {
+            mainColor = Color.TRANSPARENT;
+            accentCandidate = Color.TRANSPARENT;
+        } else {
+            mainColor = getDominantColor(currentColors);
+            accentCandidate = getAccentColor(currentColors);
         }
 
-        if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate.toArgb()) {
+        if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate) {
             return;
         }
 
         mMainWallpaperColor = mainColor;
-        mWallpaperAccentColor = accentCandidate.toArgb();
+        mWallpaperAccentColor = accentCandidate;
 
         // Let's compare these colors to our finite set of overlays, and then pick an overlay.
         List<Integer> systemColors = mThemeManager.getAvailableSystemColors();
@@ -244,10 +239,28 @@
     }
 
     /**
+     * Return the main theme color from a given {@link WallpaperColors} instance.
+     */
+    protected int getDominantColor(@NonNull WallpaperColors wallpaperColors) {
+        return wallpaperColors.getPrimaryColor().toArgb();
+    }
+
+    protected int getAccentColor(@NonNull WallpaperColors wallpaperColors) {
+        Color accentCandidate = wallpaperColors.getSecondaryColor();
+        if (accentCandidate == null) {
+            accentCandidate = wallpaperColors.getTertiaryColor();
+        }
+        if (accentCandidate == null) {
+            accentCandidate = wallpaperColors.getPrimaryColor();
+        }
+        return accentCandidate.toArgb();
+    }
+
+    /**
      * Given a color and a list of candidates, return the candidate that's the most similar to the
      * given color.
      */
-    private static int getClosest(List<Integer> candidates, int color) {
+    protected int getClosest(List<Integer> candidates, int color) {
         float[] hslMain = new float[3];
         float[] hslCandidate = new float[3];
 
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index 8dea5b5..125b5d4c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -36,7 +36,7 @@
 import com.android.wm.shell.pip.tv.PipControlsViewController;
 import com.android.wm.shell.pip.tv.PipNotification;
 import com.android.wm.shell.pip.tv.TvPipMenuController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 
@@ -120,7 +120,7 @@
             PipBoundsState pipBoundsState,
             PipBoundsAlgorithm pipBoundsAlgorithm,
             PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
-            Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
+            Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController,
             PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
         return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm,
                 tvMenuController, pipSurfaceTransactionHelper, splitScreenOptional,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 06f1522..765fd32 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -29,8 +29,8 @@
 import com.android.wm.shell.common.SystemWindows;
 import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 
 import java.util.concurrent.Executor;
 
@@ -54,12 +54,12 @@
 
     @WMSingleton
     @Provides
-    static SplitScreen provideSplitScreen(Context context,
+    static LegacySplitScreen provideSplitScreen(Context context,
             DisplayController displayController, SystemWindows systemWindows,
             DisplayImeController displayImeController, @Main Handler handler,
             TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) {
-        return new SplitScreenController(context, displayController, systemWindows,
+        return new LegacySplitScreenController(context, displayController, systemWindows,
                 displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue,
                 taskStackListener);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 2a18f3c5..0819429 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -61,7 +61,7 @@
 import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.protolog.ShellProtoLogImpl;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -93,7 +93,7 @@
     private final ScreenLifecycle mScreenLifecycle;
     private final SysUiState mSysUiState;
     private final Optional<Pip> mPipOptional;
-    private final Optional<SplitScreen> mSplitScreenOptional;
+    private final Optional<LegacySplitScreen> mSplitScreenOptional;
     private final Optional<OneHanded> mOneHandedOptional;
     private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
     private final ProtoTracer mProtoTracer;
@@ -112,7 +112,7 @@
             ScreenLifecycle screenLifecycle,
             SysUiState sysUiState,
             Optional<Pip> pipOptional,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> splitScreenOptional,
             Optional<OneHanded> oneHandedOptional,
             Optional<HideDisplayCutout> hideDisplayCutoutOptional,
             ProtoTracer protoTracer,
@@ -190,7 +190,7 @@
     }
 
     @VisibleForTesting
-    void initSplitScreen(SplitScreen splitScreen) {
+    void initSplitScreen(LegacySplitScreen legacySplitScreen) {
         mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() {
             @Override
             public void onKeyguardVisibilityChanged(boolean showing) {
@@ -198,7 +198,7 @@
                 // above everything, it is actually transparent except for notifications, so
                 // we still need to hide any surfaces that are below it.
                 // TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
-                splitScreen.onKeyguardVisibilityChanged(showing);
+                legacySplitScreen.onKeyguardVisibilityChanged(showing);
             }
         };
         mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index ee58947..bcb2a8c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -34,6 +34,7 @@
 import com.android.systemui.dagger.WMSingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.wm.shell.FullscreenTaskListener;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellCommandHandler;
 import com.android.wm.shell.ShellInit;
 import com.android.wm.shell.ShellTaskOrganizer;
@@ -65,7 +66,7 @@
 import com.android.wm.shell.pip.PipUiEventLogger;
 import com.android.wm.shell.pip.phone.PipAppOpsListener;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
@@ -169,14 +170,14 @@
     static ShellInit provideShellInit(DisplayImeController displayImeController,
             DragAndDropController dragAndDropController,
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<AppPairs> appPairsOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Transitions transitions) {
         return new ShellInit(displayImeController,
                 dragAndDropController,
                 shellTaskOrganizer,
-                splitScreenOptional,
+                legacySplitScreenOptional,
                 appPairsOptional,
                 fullscreenTaskListener,
                 transitions);
@@ -190,12 +191,12 @@
     @Provides
     static Optional<ShellCommandHandler> provideShellCommandHandler(
             ShellTaskOrganizer shellTaskOrganizer,
-            Optional<SplitScreen> splitScreenOptional,
+            Optional<LegacySplitScreen> legacySplitScreenOptional,
             Optional<Pip> pipOptional,
             Optional<OneHanded> oneHandedOptional,
             Optional<HideDisplayCutout> hideDisplayCutout,
             Optional<AppPairs> appPairsOptional) {
-        return Optional.of(new ShellCommandHandler(shellTaskOrganizer, splitScreenOptional,
+        return Optional.of(new ShellCommandHandler(shellTaskOrganizer, legacySplitScreenOptional,
                 pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional));
     }
 
@@ -282,12 +283,19 @@
 
     @WMSingleton
     @Provides
+    static RootTaskDisplayAreaOrganizer provideRootTaskDisplayAreaOrganizer(
+            @ShellMainThread ShellExecutor mainExecutor, Context context) {
+        return new RootTaskDisplayAreaOrganizer(mainExecutor);
+    }
+
+    @WMSingleton
+    @Provides
     static TaskStackListenerImpl providerTaskStackListenerImpl(@Main Handler handler) {
         return new TaskStackListenerImpl(handler);
     }
 
     @BindsOptionalOf
-    abstract SplitScreen optionalSplitScreen();
+    abstract LegacySplitScreen optionalLegacySplitScreen();
 
     @BindsOptionalOf
     abstract AppPairs optionalAppPairs();
@@ -311,16 +319,18 @@
     @WMSingleton
     @Provides
     static Optional<OneHanded> provideOneHandedController(Context context,
-            DisplayController displayController, TaskStackListenerImpl taskStackListener) {
+            DisplayController displayController, TaskStackListenerImpl taskStackListener,
+            @ShellMainThread ShellExecutor mainExecutor) {
         return Optional.ofNullable(OneHandedController.create(context, displayController,
-                taskStackListener));
+                taskStackListener, mainExecutor));
     }
 
     @WMSingleton
     @Provides
     static Optional<HideDisplayCutout> provideHideDisplayCutoutController(Context context,
-            DisplayController displayController) {
-        return Optional.ofNullable(HideDisplayCutoutController.create(context, displayController));
+            DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor) {
+        return Optional.ofNullable(
+                HideDisplayCutoutController.create(context, displayController, mainExecutor));
     }
 
     @WMSingleton
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 281b1aa..3399a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -46,8 +46,8 @@
 import com.android.wm.shell.pip.phone.PipAppOpsListener;
 import com.android.wm.shell.pip.phone.PipController;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -72,12 +72,12 @@
 
     @WMSingleton
     @Provides
-    static SplitScreen provideSplitScreen(Context context,
+    static LegacySplitScreen provideLegacySplitScreen(Context context,
             DisplayController displayController, SystemWindows systemWindows,
             DisplayImeController displayImeController, @Main Handler handler,
             TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) {
-        return new SplitScreenController(context, displayController, systemWindows,
+        return new LegacySplitScreenController(context, displayController, systemWindows,
                 displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue,
                 taskStackListener);
     }
@@ -145,7 +145,7 @@
             PipBoundsAlgorithm pipBoundsAlgorithm,
             PhonePipMenuController menuPhoneController,
             PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
-            Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
+            Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController,
             PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
         return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm,
                 menuPhoneController, pipSurfaceTransactionHelper, splitScreenOptional,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index e967a5d..6c3b37e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -24,10 +24,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -54,8 +51,6 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.util.time.FakeSystemClock;
 
-import junit.framework.Assert;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -84,8 +79,7 @@
         MockitoAnnotations.initMocks(this);
         mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
         mListener = new ForegroundServiceNotificationListener(
-                mContext, mFsc, mEntryManager, mNotifPipeline,
-                mock(ForegroundServiceLifetimeExtender.class), mClock);
+                mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
         ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
                 ArgumentCaptor.forClass(NotificationEntryListener.class);
         verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
deleted file mode 100644
index 9a40421..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
+++ /dev/null
@@ -1,110 +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;
-
-import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Notification;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.systemui.statusbar.NotificationInteractionTracker;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.util.time.FakeSystemClock;
-
-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 ForegroundServiceNotificationListenerTest extends SysuiTestCase {
-    private ForegroundServiceLifetimeExtender mExtender;
-    private NotificationEntry mEntry;
-    private Notification mNotif;
-    private final FakeSystemClock mClock = new FakeSystemClock();
-
-    @Mock
-    private NotificationInteractionTracker mInteractionTracker;
-
-    @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        mExtender = new ForegroundServiceLifetimeExtender(mInteractionTracker, mClock);
-
-        mNotif = new Notification.Builder(mContext, "")
-                .setSmallIcon(R.drawable.ic_person)
-                .setContentTitle("Title")
-                .setContentText("Text")
-                .build();
-
-        mEntry = new NotificationEntryBuilder()
-                .setCreationTime(mClock.uptimeMillis())
-                .setNotification(mNotif)
-                .build();
-    }
-
-    /**
-     * ForegroundServiceLifetimeExtenderTest
-     */
-    @Test
-    public void testShouldExtendLifetime_should_foreground() {
-        // Extend the lifetime of a FGS notification iff it has not been visible
-        // for the minimum time
-        mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
-        // No time has elapsed, keep showing
-        assertTrue(mExtender.shouldExtendLifetime(mEntry));
-    }
-
-    @Test
-    public void testShouldExtendLifetime_shouldNot_foreground() {
-        mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
-        // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1
-        mClock.advanceTime(MIN_FGS_TIME_MS + 1);
-        assertFalse(mExtender.shouldExtendLifetime(mEntry));
-    }
-
-    @Test
-    public void testShouldExtendLifetime_shouldNot_notForeground() {
-        mNotif.flags = 0;
-
-        // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1
-        mClock.advanceTime(MIN_FGS_TIME_MS + 1);
-        assertFalse(mExtender.shouldExtendLifetime(mEntry));
-    }
-
-    @Test
-    public void testShouldExtendLifetime_shouldNot_interruped() {
-        // GIVEN a notification that would trigger lifetime extension
-        mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
-        // GIVEN the notification has alerted
-        mEntry.setInterruption();
-
-        // THEN the notification does not need to have its lifetime extended by this extender
-        assertFalse(mExtender.shouldExtendLifetime(mEntry));
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 32c360f..96f46eaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -60,7 +60,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.After;
 import org.junit.Before;
@@ -98,7 +98,7 @@
                         mock(BroadcastDispatcher.class),
                         mock(CommandQueue.class),
                         Optional.of(mock(Pip.class)),
-                        Optional.of(mock(SplitScreen.class)),
+                        Optional.of(mock(LegacySplitScreen.class)),
                         Optional.of(mock(Recents.class)),
                         () -> mock(StatusBar.class),
                         mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 57eac74..851d486 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -77,7 +77,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -225,7 +225,7 @@
                 mBroadcastDispatcher,
                 mCommandQueue,
                 Optional.of(mock(Pip.class)),
-                Optional.of(mock(SplitScreen.class)),
+                Optional.of(mock(LegacySplitScreen.class)),
                 Optional.of(mock(Recents.class)),
                 () -> mock(StatusBar.class),
                 mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
new file mode 100644
index 0000000..e934f84
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.people;
+
+import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.appwidget.IAppWidgetService;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.SbnBuilder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class PeopleSpaceUtilsTest extends SysuiTestCase {
+
+    private static final int WIDGET_ID_WITH_SHORTCUT = 1;
+    private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
+    private static final String SHORTCUT_ID = "101";
+    private static final String NOTIFICATION_KEY = "notification_key";
+    private static final String NOTIFICATION_CONTENT = "notification_content";
+
+    @Mock
+    private NotificationListener mListenerService;
+    @Mock
+    private IAppWidgetService mIAppWidgetService;
+    @Mock
+    private AppWidgetManager mAppWidgetManager;
+
+    private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
+    private static Uri sUri = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority("something")
+            .path("test")
+            .build();
+    private static Person sPerson = new Person.Builder()
+            .setName("name")
+            .setKey("abc")
+            .setUri("uri")
+            .setBot(false)
+            .build();
+    private static PeopleSpaceTile sPeopleSpaceTile =
+            new PeopleSpaceTile
+                    .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
+                    .setNotificationKey(NOTIFICATION_KEY)
+                    .setNotificationContent(NOTIFICATION_CONTENT)
+                    .setNotificationDataUri(sUri)
+                    .build();
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        Bundle options = new Bundle();
+        options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
+                .thenReturn(options);
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
+                .thenReturn(new Bundle());
+    }
+
+    @Test
+    public void testGetLastMessagingStyleMessageNoMessage() {
+        Notification notification = new Notification.Builder(mContext, "test")
+                .setContentTitle("TEST_TITLE")
+                .setContentText("TEST_TEXT")
+                .setShortcutId(SHORTCUT_ID)
+                .build();
+        StatusBarNotification sbn = new SbnBuilder()
+                .setNotification(notification)
+                .build();
+
+        Notification.MessagingStyle.Message lastMessage =
+                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+
+        assertThat(lastMessage).isNull();
+    }
+
+    @Test
+    public void testGetLastMessagingStyleMessage() {
+        Notification notification = new Notification.Builder(mContext, "test")
+                .setContentTitle("TEST_TITLE")
+                .setContentText("TEST_TEXT")
+                .setShortcutId(SHORTCUT_ID)
+                .setStyle(new Notification.MessagingStyle(sPerson)
+                        .addMessage(new Notification.MessagingStyle.Message("text1", 0, sPerson))
+                        .addMessage(new Notification.MessagingStyle.Message("text2", 20, sPerson))
+                        .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+                )
+                .build();
+        StatusBarNotification sbn = new SbnBuilder()
+                .setNotification(notification)
+                .build();
+
+        Notification.MessagingStyle.Message lastMessage =
+                PeopleSpaceUtils.getLastMessagingStyleMessage(sbn);
+
+        assertThat(lastMessage.getText()).isEqualTo("text2");
+    }
+
+    @Test
+    public void testAugmentTileFromStorageWithNotification() {
+        PeopleSpaceTile tile =
+                new PeopleSpaceTile
+                        .Builder("id", "userName", sIcon, new Intent())
+                        .build();
+        PeopleSpaceTile actual = PeopleSpaceUtils
+                .augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITH_SHORTCUT);
+
+        assertThat(actual.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
+        assertThat(actual.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
+        assertThat(actual.getNotificationDataUri()).isEqualTo(sUri);
+    }
+
+    @Test
+    public void testAugmentTileFromStorageWithoutNotification() {
+        PeopleSpaceTile tile =
+                new PeopleSpaceTile
+                        .Builder("id", "userName", sIcon, new Intent())
+                        .build();
+        PeopleSpaceTile actual = PeopleSpaceUtils
+                .augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITHOUT_SHORTCUT);
+
+        assertThat(actual.getNotificationKey()).isEqualTo(null);
+        assertThat(actual.getNotificationKey()).isEqualTo(null);
+        assertThat(actual.getNotificationDataUri()).isEqualTo(null);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 019424c..cd4f51e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -19,6 +19,8 @@
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 
+import static com.android.systemui.people.PeopleSpaceUtils.OPTIONS_PEOPLE_SPACE_TILE;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -30,15 +32,24 @@
 import static java.util.Objects.requireNonNull;
 
 import android.app.INotificationManager;
+import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.Person;
+import android.app.people.PeopleSpaceTile;
 import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.ConversationChannelWrapper;
+import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 import android.widget.RemoteViews;
 
@@ -46,9 +57,11 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.appwidget.IAppWidgetService;
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
+import com.android.systemui.statusbar.SbnBuilder;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -79,6 +92,9 @@
     private static final int WIDGET_ID_WITH_SHORTCUT = 1;
     private static final int WIDGET_ID_WITHOUT_SHORTCUT = 2;
     private static final String SHORTCUT_ID = "101";
+    private static final String OTHER_SHORTCUT_ID = "102";
+    private static final String NOTIFICATION_KEY = "notification_key";
+    private static final String NOTIFICATION_CONTENT = "notification_content";
 
     private PeopleSpaceWidgetManager mManager;
 
@@ -94,6 +110,26 @@
     @Captor
     private ArgumentCaptor<NotificationHandler> mListenerCaptor;
 
+    private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
+    private static Uri sUri = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority("something")
+            .path("test")
+            .build();
+    private static Person sPerson = new Person.Builder()
+            .setName("name")
+            .setKey("abc")
+            .setUri("uri")
+            .setBot(false)
+            .build();
+    private static PeopleSpaceTile sPeopleSpaceTile =
+            new PeopleSpaceTile
+                    .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
+                    .setNotificationKey(NOTIFICATION_KEY)
+                    .setNotificationContent(NOTIFICATION_CONTENT)
+                    .setNotificationDataUri(sUri)
+                    .build();
+
     private final NoManSimulator mNoMan = new NoManSimulator();
     private final FakeSystemClock mClock = new FakeSystemClock();
 
@@ -110,6 +146,18 @@
         mNoMan.addListener(serviceListener);
         Settings.Global.putInt(mContext.getContentResolver(),
                 Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 2);
+
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
+        editor.commit();
+        Bundle options = new Bundle();
+        options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
+                .thenReturn(options);
+        when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
+                .thenReturn(new Bundle());
     }
 
     @Test
@@ -123,7 +171,6 @@
                         .setPkg(TEST_PACKAGE_A));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
     }
 
@@ -140,7 +187,6 @@
                         .setPkg(TEST_PACKAGE_A));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mAppWidgetManager, never()).updateAppWidget(anyInt(), any(RemoteViews.class));
         verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
     }
@@ -156,7 +202,6 @@
                         .setPkg(TEST_PACKAGE_A));
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(1))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mIAppWidgetService, never()).updateAppWidgetIds(any(), any(),
@@ -171,17 +216,12 @@
         when(mINotificationManager.getConversations(true)).thenReturn(
                 new ParceledListSlice(getConversationWithShortcutId()));
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
-        SharedPreferences.Editor editor = sp.edit();
-        editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
-        editor.commit();
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
                 .setPkg(TEST_PACKAGE_A)
                 .setId(1));
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, never())
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
@@ -198,10 +238,6 @@
         when(mINotificationManager.getConversations(true)).thenReturn(
                 new ParceledListSlice(getConversationWithShortcutId()));
         int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
-        SharedPreferences.Editor editor = sp.edit();
-        editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
-        editor.commit();
         when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
 
         NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
@@ -212,7 +248,6 @@
                 .setPkg(TEST_PACKAGE_B)
                 .setId(2));
 
-        verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
         verify(mIAppWidgetService, never())
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mAppWidgetManager, times(2)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
@@ -234,7 +269,6 @@
                 .setPkg(TEST_PACKAGE_B)
                 .setId(2));
 
-        verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(2))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
@@ -252,7 +286,6 @@
         mClock.advanceTime(4);
         NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
 
-        verify(mIAppWidgetService, times(2)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(2))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
@@ -290,13 +323,124 @@
                 UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
         mClock.advanceTime(MIN_LINGER_DURATION);
 
-        verify(mIAppWidgetService, times(1)).getAppWidgetIds(any());
         verify(mIAppWidgetService, times(1))
                 .notifyAppWidgetViewDataChanged(any(), eq(widgetIdsArray), anyInt());
         verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
                 any(RemoteViews.class));
     }
 
+    @Test
+    public void testDoNotUpdateNotificationPostedIfNoExistingTile() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, never())
+                .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+    }
+
+    @Test
+    public void testDoNotUpdateNotificationRemovedIfNoExistingTile() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        StatusBarNotification sbn = createConversationNotification(OTHER_SHORTCUT_ID);
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(4);
+        NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, never())
+                .updateAppWidgetOptions(anyInt(), any());
+    }
+
+    @Test
+    public void testUpdateNotificationPostedIfExistingTile() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        StatusBarNotification sbn = createConversationNotification(SHORTCUT_ID);
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, times(1))
+                .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+    }
+
+    @Test
+    public void testDoNotUpdateNotificationPostedWithoutMessagesIfExistingTile()
+            throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        Notification notification = new Notification.Builder(mContext)
+                .setContentTitle("TEST_TITLE")
+                .setContentText("TEST_TEXT")
+                .setShortcutId(SHORTCUT_ID)
+                .build();
+        StatusBarNotification sbn = new SbnBuilder()
+                .setNotification(notification)
+                .build();
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, never())
+                .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+    }
+
+    @Test
+    public void testUpdateNotificationRemovedIfExistingTile() throws RemoteException {
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
+        when(mINotificationManager.getConversations(true)).thenReturn(
+                new ParceledListSlice(getConversationWithShortcutId()));
+        int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
+        when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
+
+        StatusBarNotification sbn = createConversationNotification(SHORTCUT_ID);
+        NotifEvent notif1 = mNoMan.postNotif(new NotificationEntryBuilder()
+                .setSbn(sbn)
+                .setPkg(TEST_PACKAGE_A)
+                .setId(1));
+        mClock.advanceTime(MIN_LINGER_DURATION);
+        NotifEvent notif1b = mNoMan.retractNotif(notif1.sbn, 0);
+        mClock.advanceTime(MIN_LINGER_DURATION);
+
+        verify(mAppWidgetManager, times(2))
+                .updateAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT), any());
+    }
+
     /** Returns a list of a single conversation associated with {@code SHORTCUT_ID}. */
     private List<ConversationChannelWrapper> getConversationWithShortcutId() {
         List<ConversationChannelWrapper> convos = new ArrayList<>();
@@ -306,4 +450,18 @@
         convos.add(convo1);
         return convos;
     }
+
+    private StatusBarNotification createConversationNotification(String shortcutId) {
+        Notification notification = new Notification.Builder(mContext)
+                .setContentTitle("TEST_TITLE")
+                .setContentText("TEST_TEXT")
+                .setShortcutId(shortcutId)
+                .setStyle(new Notification.MessagingStyle(sPerson)
+                        .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+                )
+                .build();
+        return new SbnBuilder()
+                .setNotification(notification)
+                .build();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index a6c2d08..14de7aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -103,6 +103,7 @@
         when(mQSPanel.isAttachedToWindow()).thenReturn(true);
         when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
         when(mQSPanel.createRegularTileLayout()).thenReturn(mPagedTileLayout);
+        when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
         when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
         when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
         when(mToggleSliderViewControllerFactory.create(any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 3f2b4da..c490c4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -24,12 +24,14 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.media.MediaHost
 import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.qs.QSTileView
 import com.android.systemui.qs.customize.QSCustomizerController
 import com.android.systemui.qs.logging.QSLogger
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.any
@@ -59,6 +61,8 @@
     private lateinit var tile: QSTile
     @Mock
     private lateinit var tileLayout: TileLayout
+    @Mock
+    private lateinit var tileView: QSTileView
 
     private lateinit var controller: QuickQSPanelController
 
@@ -68,6 +72,7 @@
 
         `when`(quickQSPanel.tileLayout).thenReturn(tileLayout)
         `when`(quickQSPanel.dumpableTag).thenReturn("")
+        `when`(qsTileHost.createTileView(any(), anyBoolean())).thenReturn(tileView)
 
         controller = QuickQSPanelController(
                 quickQSPanel,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
index 0c3db57..b3176dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
@@ -41,7 +41,7 @@
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +70,7 @@
     @Mock private NavigationModeController mMockNavModeController;
     @Mock private NotificationShadeWindowController mMockStatusBarWinController;
     @Mock private Optional<Pip> mMockPipOptional;
-    @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
+    @Mock private Optional<LegacySplitScreen> mMockSplitScreenOptional;
     @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
     @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
     @Mock private PackageManager mPackageManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
index fb8c3d9..3f1cf83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
@@ -25,6 +25,12 @@
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
 
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_UNCHANGED;
+
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -40,6 +46,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 
+import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -76,28 +84,46 @@
     }
 
     @Test
-    public void testShowFeedbackIndicator_settingDisabled() {
+    public void testFeedback_settingDisabled() {
         switchSetting(OFF);
+        assertEquals(STATUS_UNCHANGED, mAssistantFeedbackController.getFeedbackStatus(
+                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
         assertFalse(mAssistantFeedbackController.showFeedbackIndicator(
                 getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
     }
 
     @Test
-    public void testShowFeedbackIndicator_changedImportance() {
-        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
-                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED)));
-        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
-                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED)));
-        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
-                getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED)));
+    public void testFeedback_changedImportance() {
+        NotificationEntry entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED);
+        assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+        entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED);
+        assertEquals(STATUS_SILENCED, mAssistantFeedbackController.getFeedbackStatus(entry));
+        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+        entry = getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED);
+        assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
     }
 
     @Test
-    public void testShowFeedbackIndicator_changedRanking() {
-        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
-                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED)));
-        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
-                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED)));
+    public void testFeedback_changedRanking() {
+        NotificationEntry entry =
+                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED);
+        assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+        entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED);
+        assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+        assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+    }
+
+    @Test
+    public void testGetFeedbackImageResource_settingDisabled() {
+        switchSetting(OFF);
+        Assert.assertEquals(0, mAssistantFeedbackController.getFeedbackImageResource(
+                getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
     }
 
     private NotificationEntry getEntry(int oldImportance, int newImportance,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index 639e791..0954621 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -31,7 +31,6 @@
 import android.app.Notification;
 import android.os.Bundle;
 import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -46,7 +45,6 @@
 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.listbuilder.pluggable.NotifSectioner;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -71,7 +69,6 @@
     private NotificationEntryBuilder mEntryBuilder;
     private AppOpsCoordinator mAppOpsCoordinator;
     private NotifFilter mForegroundFilter;
-    private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
     private NotifSectioner mFgsSection;
 
     private FakeSystemClock mClock = new FakeSystemClock();
@@ -98,13 +95,6 @@
         verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
         mForegroundFilter = filterCaptor.getValue();
 
-        // capture lifetime extender
-        ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor =
-                ArgumentCaptor.forClass(NotifLifetimeExtender.class);
-        verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
-                lifetimeExtenderCaptor.capture());
-        mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue();
-
         mFgsSection = mAppOpsCoordinator.getSectioner();
     }
 
@@ -160,55 +150,6 @@
     }
 
     @Test
-    public void extendLifetimeText_notForeground() {
-        // GIVEN the notification doesn't represent a foreground service
-        mEntryBuilder.modifyNotification(mContext)
-                .setFlag(FLAG_FOREGROUND_SERVICE, false);
-
-        // THEN don't extend the lifetime
-        assertFalse(mForegroundNotifLifetimeExtender
-                .shouldExtendLifetime(mEntryBuilder.build(),
-                        NotificationListenerService.REASON_CLICK));
-    }
-
-    @Test
-    public void extendLifetimeText_foregroundNotifRecentlyPosted() {
-        // GIVEN the notification represents a foreground service that was just posted
-        Notification notification = new Notification.Builder(mContext, "test_channel")
-                .setFlag(FLAG_FOREGROUND_SERVICE, true)
-                .build();
-        NotificationEntry entry = mEntryBuilder
-                .setSbn(new StatusBarNotification(TEST_PKG, TEST_PKG, NOTIF_USER_ID, "",
-                        NOTIF_USER_ID, NOTIF_USER_ID, notification,
-                        new UserHandle(NOTIF_USER_ID), "", System.currentTimeMillis()))
-                .setNotification(notification)
-                .build();
-
-        // THEN extend the lifetime
-        assertTrue(mForegroundNotifLifetimeExtender
-                .shouldExtendLifetime(entry, NotificationListenerService.REASON_CLICK));
-    }
-
-    @Test
-    public void extendLifetimeText_foregroundNotifOld() {
-        // GIVEN the notification represents a foreground service that was posted 10 seconds ago
-        Notification notification = new Notification.Builder(mContext, "test_channel")
-                .setFlag(FLAG_FOREGROUND_SERVICE, true)
-                .build();
-        NotificationEntry entry = mEntryBuilder
-                .setSbn(new StatusBarNotification(TEST_PKG, TEST_PKG, NOTIF_USER_ID, "",
-                        NOTIF_USER_ID, NOTIF_USER_ID, notification,
-                        new UserHandle(NOTIF_USER_ID), "",
-                        System.currentTimeMillis() - 10000))
-                .setNotification(notification)
-                .build();
-
-        // THEN don't extend the lifetime because the extended time exceeds MIN_FGS_TIME_MS
-        assertFalse(mForegroundNotifLifetimeExtender
-                .shouldExtendLifetime(entry, NotificationListenerService.REASON_CLICK));
-    }
-
-    @Test
     public void testIncludeFGSInSection_importanceDefault() {
         // GIVEN the notification represents a colorized foreground service with > min importance
         mEntryBuilder
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 891179c..ca982a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -210,7 +210,7 @@
         // public notification is custom layout - no header
         mGroupRow.setSensitive(true, true);
         mGroupRow.setOnFeedbackClickListener(null);
-        mGroupRow.showFeedbackIcon(false);
+        mGroupRow.showFeedbackIcon(false, 0);
     }
 
     @Test
@@ -224,11 +224,12 @@
         mGroupRow.setChildrenContainer(mockContainer);
 
         final boolean show = true;
-        mGroupRow.showFeedbackIcon(show);
+        final int resId = 1;
+        mGroupRow.showFeedbackIcon(show, resId);
 
-        verify(mockContainer, times(1)).showFeedbackIcon(show);
-        verify(privateLayout, times(1)).showFeedbackIcon(show);
-        verify(publicLayout, times(1)).showFeedbackIcon(show);
+        verify(mockContainer, times(1)).showFeedbackIcon(show, resId);
+        verify(privateLayout, times(1)).showFeedbackIcon(show, resId);
+        verify(publicLayout, times(1)).showFeedbackIcon(show, resId);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index 9d87579..53ff957 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -17,13 +17,13 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
 import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
 
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_ALERTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 
@@ -79,6 +79,8 @@
     private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
     private final ExpandableNotificationRow mMockNotificationRow =
             mock(ExpandableNotificationRow.class);
+    private final AssistantFeedbackController mAssistantFeedbackController =
+            mock(AssistantFeedbackController.class);
     private StatusBarNotification mSbn;
 
     @Mock
@@ -120,7 +122,7 @@
     public void testBindNotification_SetsTextApplicationName() {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mMockNotificationRow, mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mAssistantFeedbackController);
         final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
         assertTrue(textView.getText().toString().contains("App Name"));
     }
@@ -131,65 +133,60 @@
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
                 .thenReturn(iconDrawable);
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
-                mMockNotificationRow, mock(AssistantFeedbackController.class));
+                mMockNotificationRow, mAssistantFeedbackController);
         final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
 
     @Test
     public void testPrompt_silenced() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+        when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+                .thenReturn(STATUS_SILENCED);
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was silenced by the system. Was this correct?",
-                prompt.getText());
+        assertEquals("This notification was automatically demoted to Silent by the system. "
+                        + "Was this correct?", prompt.getText().toString());
     }
 
     @Test
-    public void testPrompt_promoted_importance() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+    public void testPrompt_promoted() {
+        when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+                .thenReturn(STATUS_PROMOTED);
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was promoted by the system. Was this correct?",
-                prompt.getText());
+        assertEquals("This notification was automatically ranked higher in your shade. "
+                        + "Was this correct?", prompt.getText().toString());
     }
 
     @Test
-    public void testPrompt_promoted_ranking() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+    public void testPrompt_alerted() {
+        when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+                .thenReturn(STATUS_ALERTED);
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was promoted by the system. Was this correct?",
-                prompt.getText());
+        assertEquals("This notification was automatically promoted to Default by the system. "
+                        + "Was this correct?",
+                prompt.getText().toString());
     }
 
     @Test
-    public void testPrompt_demoted_importance() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW,
-                IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+    public void testPrompt_demoted() {
+        when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+                .thenReturn(STATUS_DEMOTED);
+        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+                mAssistantFeedbackController);
         TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was demoted by the system. Was this correct?",
-                prompt.getText());
-    }
-
-    @Test
-    public void testPrompt_demoted_ranking() {
-        mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
-                IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
-        TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
-        assertEquals("This notification was demoted by the system. Was this correct?",
-                prompt.getText());
+        assertEquals("This notification was automatically ranked lower in your shade. "
+                        + "Was this correct?", prompt.getText().toString());
     }
 
     @Test
     public void testPositiveFeedback() {
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+                mAssistantFeedbackController);
 
         final View yes = mFeedbackInfo.findViewById(R.id.yes);
         yes.performClick();
@@ -206,7 +203,7 @@
                 .thenReturn(true);
 
         mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
-                mock(AssistantFeedbackController.class));
+                mAssistantFeedbackController);
 
         final View no = mFeedbackInfo.findViewById(R.id.no);
         no.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index 2101ea1..377a69d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -95,7 +95,7 @@
         mView.setExpandedChild(mockExpanded);
         mView.setHeadsUpChild(mockHeadsUp);
 
-        mView.showFeedbackIcon(true);
+        mView.showFeedbackIcon(true, 1);
 
         verify(mockContracted, times(1)).setVisibility(View.VISIBLE);
         verify(mockExpanded, times(1)).setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 3000b8b..458a058 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -374,7 +374,7 @@
                 eq(false),
                 eq(false),
                 eq(true), /* wasShownHighPriority */
-                eq(false) /* showAutomaticSetting */);
+                eq(mAssistantFeedbackController));
     }
 
     @Test
@@ -408,7 +408,7 @@
                 eq(true),
                 eq(false),
                 eq(false), /* wasShownHighPriority */
-                eq(false) /* showAutomaticSetting */);
+                eq(mAssistantFeedbackController));
     }
 
     @Test
@@ -440,7 +440,7 @@
                 eq(false),
                 eq(false),
                 eq(false), /* wasShownHighPriority */
-                eq(false) /* showAutomaticSetting */);
+                eq(mAssistantFeedbackController));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 4a2cbcc..324f0ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -64,6 +64,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 
@@ -113,6 +114,8 @@
     private OnUserInteractionCallback mOnUserInteractionCallback;
     @Mock
     private ChannelEditorDialogController mChannelEditorDialogController;
+    @Mock
+    private AssistantFeedbackController mAssistantFeedbackController;
 
     @Before
     public void setUp() throws Exception {
@@ -160,6 +163,9 @@
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
         mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();
+        when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(false);
+        when(mAssistantFeedbackController.getInlineDescriptionResource(any()))
+                .thenReturn(R.string.notification_channel_summary_automatic);
     }
 
     @Test
@@ -180,7 +186,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
         assertTrue(textView.getText().toString().contains("App Name"));
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -206,7 +212,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final ImageView iconView = mNotificationInfo.findViewById(R.id.pkg_icon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
@@ -228,7 +234,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
         assertEquals(GONE, nameView.getVisibility());
     }
@@ -259,7 +265,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
         assertEquals(VISIBLE, nameView.getVisibility());
         assertTrue(nameView.getText().toString().contains("Proxied"));
@@ -282,7 +288,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(GONE, groupNameView.getVisibility());
     }
@@ -310,7 +316,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(View.VISIBLE, groupNameView.getVisibility());
         assertEquals("Test Group Name", groupNameView.getText());
@@ -333,7 +339,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(TEST_CHANNEL_NAME, textView.getText());
     }
@@ -355,7 +361,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, textView.getVisibility());
     }
@@ -381,7 +387,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -403,7 +409,7 @@
                 true,
                 true,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -429,7 +435,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         settingsButton.performClick();
@@ -454,7 +460,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -479,7 +485,7 @@
                 false,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -501,7 +507,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
                 mMockINotificationManager,
@@ -517,7 +523,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertEquals(View.VISIBLE, settingsButton.getVisibility());
     }
@@ -542,7 +548,7 @@
                 true,
                 true,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.info).performClick();
         // Verify that listener was triggered.
@@ -568,7 +574,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView channelNameView =
                 mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, channelNameView.getVisibility());
@@ -592,7 +598,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         assertEquals(GONE, mNotificationInfo.findViewById(
                 R.id.interruptiveness_settings).getVisibility());
         assertEquals(VISIBLE, mNotificationInfo.findViewById(
@@ -616,7 +622,7 @@
                 true,
                 true,
                 true,
-                false);
+                mAssistantFeedbackController);
         final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -627,6 +633,7 @@
 
     @Test
     public void testBindNotification_automaticIsVisible() throws Exception {
+        when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
                 mMockINotificationManager,
@@ -642,7 +649,7 @@
                 true,
                 false,
                 true,
-                true);
+                mAssistantFeedbackController);
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic).getVisibility());
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility());
     }
@@ -664,13 +671,14 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic).getVisibility());
         assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility());
     }
 
     @Test
     public void testBindNotification_automaticIsSelected() throws Exception {
+        when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
         mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
@@ -687,7 +695,7 @@
                 true,
                 false,
                 true,
-                true);
+                mAssistantFeedbackController);
         assertTrue(mNotificationInfo.findViewById(R.id.automatic).isSelected());
     }
 
@@ -708,7 +716,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         assertTrue(mNotificationInfo.findViewById(R.id.alert).isSelected());
     }
 
@@ -729,7 +737,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
         assertTrue(mNotificationInfo.findViewById(R.id.silence).isSelected());
     }
 
@@ -750,7 +758,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -773,7 +781,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
         assertEquals(1, mUiEventLogger.numLogs());
         assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
                 mUiEventLogger.eventId(0));
@@ -797,7 +805,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
         mTestableLooper.processAllMessages();
@@ -824,7 +832,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.silence).performClick();
         mTestableLooper.processAllMessages();
@@ -851,7 +859,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.automatic).performClick();
         mTestableLooper.processAllMessages();
@@ -862,6 +870,7 @@
     @Test
     public void testHandleCloseControls_persistAutomatic()
             throws Exception {
+        when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
         mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE);
         mNotificationInfo.bindNotification(
                 mMockPackageManager,
@@ -878,7 +887,7 @@
                 true,
                 false,
                 true,
-                true);
+                mAssistantFeedbackController);
 
         mNotificationInfo.handleCloseControls(true, false);
         mTestableLooper.processAllMessages();
@@ -905,7 +914,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.handleCloseControls(true, false);
         mTestableLooper.processAllMessages();
@@ -940,7 +949,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -968,7 +977,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.silence).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1008,7 +1017,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1026,6 +1035,7 @@
 
     @Test
     public void testAutomaticUnlocksUserImportance() throws Exception {
+        when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
         mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationChannel.lockFields(USER_LOCKED_IMPORTANCE);
         mNotificationInfo.bindNotification(
@@ -1043,7 +1053,7 @@
                 true,
                 false,
                 true,
-                true);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.automatic).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1074,7 +1084,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.silence).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1109,7 +1119,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         assertEquals(mContext.getString(R.string.inline_done_button),
                 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1147,7 +1157,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         assertEquals(mContext.getString(R.string.inline_done_button),
                 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1184,7 +1194,7 @@
                 true,
                 false,
                 true,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.silence).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1212,7 +1222,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         assertEquals(mContext.getString(R.string.inline_done_button),
                 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1243,7 +1253,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1277,7 +1287,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1310,7 +1320,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
         mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1343,7 +1353,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         mNotificationInfo.findViewById(R.id.alert).performClick();
 
@@ -1369,7 +1379,7 @@
                 true,
                 false,
                 false,
-                false);
+                mAssistantFeedbackController);
 
         assertFalse(mNotificationInfo.willBeRemoved());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 6fb4eba..8e84f1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -148,7 +148,7 @@
 import com.android.systemui.volume.VolumeComponent;
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -245,7 +245,7 @@
     @Mock private StatusBarComponent.Builder mStatusBarComponentBuilder;
     @Mock private StatusBarComponent mStatusBarComponent;
     @Mock private PluginManager mPluginManager;
-    @Mock private SplitScreen mSplitScreen;
+    @Mock private LegacySplitScreen mLegacySplitScreen;
     @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
     @Mock private LightsOutNotifController mLightsOutNotifController;
     @Mock private ViewMediatorCallback mViewMediatorCallback;
@@ -405,7 +405,7 @@
                 mCommandQueue,
                 mStatusBarComponentBuilderProvider,
                 mPluginManager,
-                Optional.of(mSplitScreen),
+                Optional.of(mLegacySplitScreen),
                 mLightsOutNotifController,
                 mStatusBarNotificationActivityStarterBuilder,
                 mShadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 18e7840..ebc45f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -26,7 +26,8 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.R;
+import com.android.settingslib.R;
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index ce9ca9d..6adf94e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -60,17 +60,18 @@
 
 import androidx.test.InstrumentationRegistry;
 
+import com.android.settingslib.R;
 import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.MobileMappings.Config;
 import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 6899217..d11aee8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -19,6 +19,7 @@
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
 
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 61f71b7..da35de9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -38,6 +38,7 @@
 import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index ef25b73..73d87b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -40,7 +40,7 @@
 import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -63,7 +63,8 @@
     @Mock SysUiState mSysUiState;
     @Mock Pip mPip;
     @Mock PipTouchHandler mPipTouchHandler;
-    @Mock SplitScreen mSplitScreen;
+    @Mock
+    LegacySplitScreen mLegacySplitScreen;
     @Mock OneHanded mOneHanded;
     @Mock HideDisplayCutout mHideDisplayCutout;
     @Mock ProtoTracer mProtoTracer;
@@ -75,7 +76,7 @@
 
         mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
                 mKeyguardUpdateMonitor, mNavigationModeController,
-                mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
+                mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mLegacySplitScreen),
                 Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), mProtoTracer,
                 Optional.of(mShellCommandHandler));
 
@@ -91,7 +92,7 @@
 
     @Test
     public void initSplitScreen_registersCallbacks() {
-        mWMShell.initSplitScreen(mSplitScreen);
+        mWMShell.initSplitScreen(mLegacySplitScreen);
 
         verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index b397782..e1af2c4 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -349,7 +349,7 @@
                                 AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD,
                                 event.getDisplayId(),
                                 mGestureDetector.getMotionEvents());
-                mAms.onGesture(gestureEvent);
+                dispatchGesture(gestureEvent);
             }
             mState.startDelegating();
         }
@@ -367,7 +367,7 @@
                             AccessibilityService.GESTURE_DOUBLE_TAP,
                             event.getDisplayId(),
                             mGestureDetector.getMotionEvents());
-            mAms.onGesture(gestureEvent);
+            dispatchGesture(gestureEvent);
         }
         if (mSendTouchExplorationEndDelayed.isPending()) {
             mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -402,13 +402,9 @@
 
     @Override
     public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) {
-        if (DEBUG) {
-            Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
-        }
         endGestureDetection(true);
         mSendTouchInteractionEndDelayed.cancel();
-        mAms.onGesture(gestureEvent);
-
+        dispatchGesture(gestureEvent);
         return true;
     }
 
@@ -444,10 +440,7 @@
                             AccessibilityService.GESTURE_UNKNOWN,
                             event.getDisplayId(),
                             mGestureDetector.getMotionEvents());
-            if (DEBUG) {
-                Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
-            }
-            mAms.onGesture(gestureEvent);
+            dispatchGesture(gestureEvent);
         }
         return false;
     }
@@ -658,7 +651,7 @@
                                         AccessibilityService.GESTURE_PASSTHROUGH,
                                         event.getDisplayId(),
                                         mGestureDetector.getMotionEvents());
-                        mAms.onGesture(gestureEvent);
+                        dispatchGesture(gestureEvent);
                     }
                     computeDraggingPointerIdIfNeeded(event);
                     pointerIdBits = 1 << mDraggingPointerId;
@@ -682,7 +675,7 @@
                                         AccessibilityService.GESTURE_PASSTHROUGH,
                                         event.getDisplayId(),
                                         mGestureDetector.getMotionEvents());
-                        mAms.onGesture(gestureEvent);
+                        dispatchGesture(gestureEvent);
                     }
                     mState.startDelegating();
                     mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
@@ -704,7 +697,7 @@
                                                     AccessibilityService.GESTURE_PASSTHROUGH,
                                                     event.getDisplayId(),
                                                     mGestureDetector.getMotionEvents());
-                                    mAms.onGesture(gestureEvent);
+                                    dispatchGesture(gestureEvent);
                                 }
                                 mState.startDelegating();
                                 if (mState.isTouchExploring()) {
@@ -725,7 +718,7 @@
                                         AccessibilityService.GESTURE_PASSTHROUGH,
                                         event.getDisplayId(),
                                         mGestureDetector.getMotionEvents());
-                        mAms.onGesture(gestureEvent);
+                        dispatchGesture(gestureEvent);
                     }
                     mState.startDelegating();
                     event = MotionEvent.obtainNoHistory(event);
@@ -1304,7 +1297,7 @@
                                 AccessibilityService.GESTURE_TOUCH_EXPLORATION,
                                 mState.getLastReceivedEvent().getDisplayId(),
                                 mGestureDetector.getMotionEvents());
-                mAms.onGesture(gestureEvent);
+                dispatchGesture(gestureEvent);
             }
             if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
                 // Deliver a down event.
@@ -1439,6 +1432,13 @@
         }
     }
 
+    private void dispatchGesture(AccessibilityGestureEvent gestureEvent) {
+        if (DEBUG) {
+            Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
+        }
+        mAms.onGesture(gestureEvent);
+    }
+
     @Override
     public String toString() {
         return "TouchExplorer { "
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 9d8901a..c7fd209 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -422,12 +422,15 @@
         @GuardedBy("mLock")
         private FillRequest mPendingFillRequest;
 
-        @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
-                boolean isInlineRequest) {
+        void newAutofillRequestLocked(boolean isInlineRequest) {
             mPendingFillRequest = null;
             mWaitForInlineRequest = isInlineRequest;
             mPendingInlineSuggestionsRequest = null;
-            return isInlineRequest ? (inlineSuggestionsRequest) -> {
+        }
+
+        @NonNull Consumer<InlineSuggestionsRequest> newInlineRequestConsumerLocked(
+                ViewState viewState) {
+            return (inlineSuggestionsRequest) -> {
                 synchronized (mLock) {
                     if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
                         return;
@@ -436,7 +439,7 @@
                     maybeRequestFillLocked();
                     viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
                 }
-            } : null;
+            };
         }
 
         void maybeRequestFillLocked() {
@@ -808,32 +811,12 @@
         // structure is taken. This causes only one fill request per burst of focus changes.
         cancelCurrentRequestLocked();
 
-        // Only ask IME to create inline suggestions request if Autofill provider supports it and
-        // the render service is available except the autofill is triggered manually and the view
-        // is also not focused.
-        final RemoteInlineSuggestionRenderService remoteRenderService =
-                mService.getRemoteInlineSuggestionRenderServiceLocked();
-        if (mSessionFlags.mInlineSupportedByService
-                && remoteRenderService != null
-                && isViewFocusedLocked(flags)) {
-            Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
-                    mAssistReceiver.newAutofillRequestLocked(viewState,
-                            /* isInlineRequest= */ true);
-            if (inlineSuggestionsRequestConsumer != null) {
-                final AutofillId focusedId = mCurrentViewId;
-                remoteRenderService.getInlineSuggestionsRendererInfo(
-                        new RemoteCallback((extras) -> {
-                            synchronized (mLock) {
-                                mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
-                                        focusedId, inlineSuggestionsRequestConsumer, extras);
-                            }
-                        }, mHandler)
-                );
-                viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
-            }
-        } else {
-            mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
-        }
+        final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
+                mAssistReceiver.newInlineRequestConsumerLocked(viewState);
+        final boolean isInlineRequest = maybeRequestCreateInlineSuggestionsRequestLocked(
+                /* isAugmented= */ false, inlineSuggestionsRequestConsumer, viewState,
+                mCurrentViewId, flags);
+        mAssistReceiver.newAutofillRequestLocked(isInlineRequest);
 
         // Now request the assist structure data.
         try {
@@ -853,6 +836,60 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private boolean maybeRequestCreateInlineSuggestionsRequestLocked(boolean isAugmented,
+            @NonNull Consumer<InlineSuggestionsRequest> requestConsumer,
+            @NonNull ViewState viewState, @NonNull AutofillId focusedId, int flags) {
+        final RemoteInlineSuggestionRenderService remoteRenderService =
+                mService.getRemoteInlineSuggestionRenderServiceLocked();
+        if (remoteRenderService == null || !isViewFocusedLocked(flags)) {
+            return false;
+        }
+
+        // Standard:
+        // Only ask IME to create inline suggestions request if Autofill provider supports it
+        // and the render service is available except the autofill is triggered manually and the
+        // view is also not focused.
+        //
+        // Augmented:
+        // When the inline suggestion render service is available and the view is focused, there
+        // are 3 cases when augmented autofill should ask IME for inline suggestion request,
+        // because standard autofill flow didn't:
+        // 1. the field is augmented autofill only (when standard autofill provider is None or
+        // when it returns null response)
+        // 2. standard autofill provider doesn't support inline suggestion
+        // 3. we re-entered the autofill session and standard autofill was not re-triggered,
+        // this is recognized by seeing mExpiredResponse == true
+        if ((!isAugmented && mSessionFlags.mInlineSupportedByService)
+                || (isAugmented && (mSessionFlags.mAugmentedAutofillOnly
+                || !mSessionFlags.mInlineSupportedByService
+                || mSessionFlags.mExpiredResponse))) {
+            if (sDebug) {
+                Slog.d(TAG, "Create inline request for "
+                        + (isAugmented ? "augmented" : "standard") + " autofill");
+            }
+            requestCreateInlineSuggestionsRequestLocked(remoteRenderService, focusedId,
+                    requestConsumer);
+            viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
+            return true;
+        }
+
+        return false;
+    }
+
+    private void requestCreateInlineSuggestionsRequestLocked(
+            @NonNull RemoteInlineSuggestionRenderService remoteRenderService,
+            @NonNull AutofillId focusedId,
+            @NonNull Consumer<InlineSuggestionsRequest> requestConsumer) {
+        remoteRenderService.getInlineSuggestionsRendererInfo(
+                new RemoteCallback((extras) -> {
+                    synchronized (mLock) {
+                        mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
+                                focusedId, requestConsumer, extras);
+                    }
+                }, mHandler));
+    }
+
     Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui,
             @NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock,
             int sessionId, int taskId, int uid, @NonNull IBinder activityToken,
@@ -2570,23 +2607,27 @@
     }
 
     /**
-     * Starts (if necessary) a new fill request upon entering a view.
+     * Invokes either regular or augmented autofill process upon entering a view.
      *
-     * <p>A new request will be started in 2 scenarios:
+     * <p> A new standard autofill request will be started in 2 scenarios:
      * <ol>
-     *   <li>If the user manually requested autofill.
-     *   <li>If the view is part of a new partition.
+     *   <li> If the user manually requested autofill.
+     *   <li> If the view is part of a new partition.
      * </ol>
+     * </p>
+     *
+     * <p> A new augmented autofill request will be started if the autofill id was marked as
+     * uninterested/unfillable by the standard service.
      *
      * @param id The id of the view that is entered.
      * @param viewState The view that is entered.
      * @param flags The flag that was passed by the AutofillManager.
      *
-     * @return {@code true} if a new fill response is requested.
+     * @return {@code true} if either regular or augmented autofill is invoked.
      */
     @GuardedBy("mLock")
-    private boolean requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id,
-            @NonNull ViewState viewState, int flags) {
+    private boolean maybeRequestFillOnViewEnteredLocked(@NonNull AutofillId id,
+            @NonNull ViewState viewState, boolean isSameViewEntered, int flags) {
         if ((flags & FLAG_MANUAL_REQUEST) != 0) {
             mSessionFlags.mAugmentedAutofillOnly = false;
             if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags);
@@ -2594,7 +2635,24 @@
             return true;
         }
 
-        // If it's not, then check if it it should start a partition.
+        if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) {
+            // Regular autofill handled the view and returned null response, but it can trigger
+            // augmented autofill.
+            if (!isSameViewEntered) {
+                if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
+                triggerAugmentedAutofillLocked(flags);
+            } else {
+                if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+            }
+            return true;
+        } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) {
+            // Regular autofill is disabled.
+            if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+            return true;
+        }
+
+        // If it's not for augmented, then check if it should start a partition for
+        // regular autofill.
         if (shouldStartNewPartitionLocked(id)) {
             if (sDebug) {
                 Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": "
@@ -2789,27 +2847,7 @@
                     return;
                 }
 
-                if ((flags & FLAG_MANUAL_REQUEST) == 0) {
-                    // Not a manual request
-                    if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(
-                            id)) {
-                        // Regular autofill handled the view and returned null response, but it
-                        // triggered augmented autofill
-                        if (!isSameViewEntered) {
-                            if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
-                            triggerAugmentedAutofillLocked(flags);
-                        } else {
-                            if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
-                        }
-                        return;
-                    } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) {
-                        // Regular autofill is disabled.
-                        if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
-                        return;
-                    }
-                }
-
-                if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) {
+                if (maybeRequestFillOnViewEnteredLocked(id, viewState, isSameViewEntered, flags)) {
                     return;
                 }
 
@@ -3407,34 +3445,12 @@
                     }
                 };
 
-        // When the inline suggestion render service is available and the view is focused, there
-        // are 3 cases when augmented autofill should ask IME for inline suggestion request,
-        // because standard autofill flow didn't:
-        // 1. the field is augmented autofill only (when standard autofill provider is None or
-        // when it returns null response)
-        // 2. standard autofill provider doesn't support inline suggestion
-        // 3. we re-entered the autofill session and standard autofill was not re-triggered, this is
-        //    recognized by seeing mExpiredResponse == true
-        final RemoteInlineSuggestionRenderService remoteRenderService =
-                mService.getRemoteInlineSuggestionRenderServiceLocked();
-        if (remoteRenderService != null
-                && (mSessionFlags.mAugmentedAutofillOnly
-                || !mSessionFlags.mInlineSupportedByService
-                || mSessionFlags.mExpiredResponse)
-                && isViewFocusedLocked(flags)) {
-            if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
-            remoteRenderService.getInlineSuggestionsRendererInfo(new RemoteCallback(
-                    (extras) -> {
-                        synchronized (mLock) {
-                            mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
-                                    focusedId, /*requestConsumer=*/ requestAugmentedAutofill,
-                                    extras);
-                        }
-                    }, mHandler));
-        } else {
+        if (!maybeRequestCreateInlineSuggestionsRequestLocked(/* isAugmented= */ true,
+                requestAugmentedAutofill, viewState, focusedId, flags)) {
             requestAugmentedAutofill.accept(
                     mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
         }
+
         if (mAugmentedAutofillDestroyer == null) {
             mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest;
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a6559f9..55c1e08 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -113,7 +113,6 @@
 import android.net.NetworkMonitorManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkProvider;
-import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.NetworkStack;
@@ -1781,14 +1780,6 @@
     }
 
     @Override
-    @Deprecated
-    public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
-        Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
-                + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
-        return new NetworkQuotaInfo();
-    }
-
-    @Override
     public boolean isActiveNetworkMetered() {
         enforceAccessPermission();
 
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 886bfb8..30fc336 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -268,7 +268,7 @@
             if (!DropBoxManagerService.this.mBooted) {
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             }
-            getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM,
+            getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                     android.Manifest.permission.READ_LOGS);
         }
 
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 086cc1c..636da6f 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -90,7 +90,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
 
@@ -419,8 +418,6 @@
                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
                 } catch (RemoteException e) {
                 }
-                FrameworkStatsLog.write_non_chained(
-                        FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
             }
         }
 
@@ -431,8 +428,6 @@
                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
                 } catch (RemoteException e) {
                 }
-                FrameworkStatsLog.write_non_chained(
-                        FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
             }
         }
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index ad547c5..6b45b48 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -108,6 +108,7 @@
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
+import android.provider.DeviceConfig;
 import android.provider.DocumentsContract;
 import android.provider.Downloads;
 import android.provider.MediaStore;
@@ -176,6 +177,7 @@
 import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -879,6 +881,8 @@
                     com.android.internal.R.bool.config_zramWriteback)) {
             ZramWriteback.scheduleZramWriteback(mContext);
         }
+
+        updateTranscodeEnabled();
     }
 
     /**
@@ -910,6 +914,21 @@
         }
     }
 
+    private void updateTranscodeEnabled() {
+        // See MediaProvider TranscodeHelper#getBooleanProperty for more information
+        boolean transcodeEnabled = false;
+        boolean defaultValue = true;
+
+        if (SystemProperties.getBoolean("persist.sys.fuse.transcode_user_control", false)) {
+            transcodeEnabled = SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled",
+                    defaultValue);
+        } else {
+            transcodeEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+                    "transcode_enabled", defaultValue);
+        }
+        SystemProperties.set("sys.fuse.transcode_enabled", String.valueOf(transcodeEnabled));
+    }
+
     /**
      * MediaProvider has a ton of code that makes assumptions about storage
      * paths never changing, so we outright kill them to pick up new state.
@@ -3534,7 +3553,7 @@
             final String description = mContext.getString(android.R.string.unknownName);
 
             res.add(new StorageVolume(id, path, path, description, primary, removable,
-                    emulated, allowMassStorage, maxFileSize, user, id, envState));
+                    emulated, allowMassStorage, maxFileSize, user, null /*uuid */, id, envState));
         }
 
         if (!foundPrimary) {
@@ -3552,12 +3571,13 @@
             final boolean allowMassStorage = false;
             final long maxFileSize = 0L;
             final UserHandle owner = new UserHandle(userId);
-            final String uuid = null;
+            final String fsUuid = null;
+            final UUID uuid = null;
             final String state = Environment.MEDIA_REMOVED;
 
             res.add(0, new StorageVolume(id, path, path,
                     description, primary, removable, emulated,
-                    allowMassStorage, maxFileSize, owner, uuid, state));
+                    allowMassStorage, maxFileSize, owner, uuid, fsUuid, state));
         }
 
         return res.toArray(new StorageVolume[res.size()]);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ae5c131..c476666 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2701,6 +2701,7 @@
         LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
                         .setCallingPackage(callingPackage)
+                        .setCallingFeatureId(callingFeatureId)
                         .setMethod(message + " events: " + events)
                         .setCallingPid(Binder.getCallingPid())
                         .setCallingUid(Binder.getCallingUid());
@@ -2859,6 +2860,7 @@
         LocationAccessPolicy.LocationPermissionQuery query =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
                         .setCallingPackage(r.callingPackage)
+                        .setCallingFeatureId(r.callingFeatureId)
                         .setCallingPid(r.callerPid)
                         .setCallingUid(r.callerUid)
                         .setMethod("TelephonyRegistry push")
@@ -2884,6 +2886,7 @@
         LocationAccessPolicy.LocationPermissionQuery query =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
                         .setCallingPackage(r.callingPackage)
+                        .setCallingFeatureId(r.callingFeatureId)
                         .setCallingPid(r.callerPid)
                         .setCallingUid(r.callerUid)
                         .setMethod("TelephonyRegistry push")
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7d6e542..a2b6304 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1672,12 +1672,13 @@
     // TODO: remove as part of fixing b/173627642
     @SuppressWarnings("AndroidFrameworkCompatChange")
     private void postFgsNotificationLocked(ServiceRecord r) {
+        final boolean isLegacyApp = (r.appInfo.targetSdkVersion < Build.VERSION_CODES.S);
         boolean showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled;
         if (!showNow) {
             // Legacy apps' FGS notifications are not deferred unless the relevant
             // DeviceConfig element has been set
             showNow = mAm.mConstants.mFlagFgsNotificationDeferralApiGated
-                    && r.appInfo.targetSdkVersion < Build.VERSION_CODES.S;
+                    && isLegacyApp;
         }
         if (!showNow) {
             // is the notification such that it should show right away?
@@ -1732,6 +1733,11 @@
             Slog.d(TAG_SERVICE, "FGS " + r
                     + " notification in " + (when - now) + " ms");
         }
+        if (isLegacyApp) {
+            Slog.i(TAG_SERVICE, "Deferring FGS notification in legacy app "
+                    + r.appInfo.packageName + "/" + UserHandle.formatUid(r.appInfo.uid)
+                    + " : " + r.foregroundNoti);
+        }
         mAm.mHandler.postAtTime(mPostDeferredFGSNotifications, when);
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index b0f296f..6892ef7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -370,9 +370,9 @@
     volatile boolean mFlagFgsNotificationDeferralEnabled = true;
 
     // Restrict FGS notification deferral policy to only those apps that target
-    // API version S or higher.  Enabled by default; set to "false" to defer FGS
-    // notifications from legacy apps as well.
-    volatile boolean mFlagFgsNotificationDeferralApiGated = true;
+    // API version S or higher.  Disabled by default; set to "true" to force
+    // legacy app FGS notifications to display immediately in all cases.
+    volatile boolean mFlagFgsNotificationDeferralApiGated = false;
 
     // Time in milliseconds to defer FGS notifications after their transition to
     // the foreground state.
@@ -806,7 +806,7 @@
         mFlagFgsNotificationDeferralApiGated = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 KEY_DEFERRED_FGS_NOTIFICATIONS_API_GATED,
-                /*default value*/ true);
+                /*default value*/ false);
     }
 
     private void updateFgsNotificationDeferralInterval() {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index f2c1e90..35f4689 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -52,7 +52,6 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
@@ -106,12 +105,18 @@
      * later restarted (hopefully due to some user action).  The value is the
      * time it was added to the list.
      *
-     * Access is synchronized on the container object itself, and no other
-     * locks may be acquired while holding that one.
+     * Read access is UNLOCKED, and must either be based on a single lookup
+     * call on the current mBadProcesses instance, or a local copy of that
+     * reference must be made and the local copy treated as the source of
+     * truth.  Mutations are performed by synchronizing on mBadProcessLock,
+     * cloning the existing mBadProcesses instance, performing the mutation,
+     * then changing the volatile "live" mBadProcesses reference to point to the
+     * mutated version.  These operations are very rare compared to lookups:
+     * we intentionally trade additional cost for mutations for eliminating
+     * lock operations from the simple lookup cases.
      */
-    @GuardedBy("mBadProcesses")
-    private final ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
-
+    private volatile ProcessMap<BadProcessInfo> mBadProcesses = new ProcessMap<>();
+    private final Object mBadProcessLock = new Object();
 
     AppErrors(Context context, ActivityManagerService service, PackageWatchdog watchdog) {
         context.assertRuntimeOverlayThemable();
@@ -128,81 +133,80 @@
         mProcessCrashTimesPersistent.clear();
         mProcessCrashShowDialogTimes.clear();
         mProcessCrashCounts.clear();
-        synchronized (mBadProcesses) {
-            mBadProcesses.clear();
+        synchronized (mBadProcessLock) {
+            mBadProcesses = new ProcessMap<>();
         }
     }
 
     void dumpDebug(ProtoOutputStream proto, long fieldId, String dumpPackage) {
-        synchronized (mBadProcesses) {
-            if (mProcessCrashTimes.getMap().isEmpty() && mBadProcesses.getMap().isEmpty()) {
-                return;
-            }
-
-            final long token = proto.start(fieldId);
-            final long now = SystemClock.uptimeMillis();
-            proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
-
-            if (!mProcessCrashTimes.getMap().isEmpty()) {
-                final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
-                final int procCount = pmap.size();
-                for (int ip = 0; ip < procCount; ip++) {
-                    final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
-                    final String pname = pmap.keyAt(ip);
-                    final SparseArray<Long> uids = pmap.valueAt(ip);
-                    final int uidCount = uids.size();
-
-                    proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
-                    for (int i = 0; i < uidCount; i++) {
-                        final int puid = uids.keyAt(i);
-                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
-                        if (dumpPackage != null
-                                && (r == null || !r.pkgList.containsKey(dumpPackage))) {
-                            continue;
-                        }
-                        final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
-                        proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
-                        proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
-                                uids.valueAt(i));
-                        proto.end(etoken);
-                    }
-                    proto.end(ctoken);
-                }
-
-            }
-
-            if (!mBadProcesses.getMap().isEmpty()) {
-                final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
-                final int processCount = pmap.size();
-                for (int ip = 0; ip < processCount; ip++) {
-                    final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
-                    final String pname = pmap.keyAt(ip);
-                    final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
-                    final int uidCount = uids.size();
-
-                    proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
-                    for (int i = 0; i < uidCount; i++) {
-                        final int puid = uids.keyAt(i);
-                        final ProcessRecord r = mService.getProcessNames().get(pname, puid);
-                        if (dumpPackage != null && (r == null
-                                || !r.pkgList.containsKey(dumpPackage))) {
-                            continue;
-                        }
-                        final BadProcessInfo info = uids.valueAt(i);
-                        final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
-                        proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
-                        proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
-                        proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
-                        proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
-                        proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
-                        proto.end(etoken);
-                    }
-                    proto.end(btoken);
-                }
-            }
-
-            proto.end(token);
+        final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
+        if (mProcessCrashTimes.getMap().isEmpty() && badProcesses.getMap().isEmpty()) {
+            return;
         }
+
+        final long token = proto.start(fieldId);
+        final long now = SystemClock.uptimeMillis();
+        proto.write(AppErrorsProto.NOW_UPTIME_MS, now);
+
+        if (!mProcessCrashTimes.getMap().isEmpty()) {
+            final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap();
+            final int procCount = pmap.size();
+            for (int ip = 0; ip < procCount; ip++) {
+                final long ctoken = proto.start(AppErrorsProto.PROCESS_CRASH_TIMES);
+                final String pname = pmap.keyAt(ip);
+                final SparseArray<Long> uids = pmap.valueAt(ip);
+                final int uidCount = uids.size();
+
+                proto.write(AppErrorsProto.ProcessCrashTime.PROCESS_NAME, pname);
+                for (int i = 0; i < uidCount; i++) {
+                    final int puid = uids.keyAt(i);
+                    final ProcessRecord r = mService.getProcessNames().get(pname, puid);
+                    if (dumpPackage != null
+                            && (r == null || !r.pkgList.containsKey(dumpPackage))) {
+                        continue;
+                    }
+                    final long etoken = proto.start(AppErrorsProto.ProcessCrashTime.ENTRIES);
+                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.UID, puid);
+                    proto.write(AppErrorsProto.ProcessCrashTime.Entry.LAST_CRASHED_AT_MS,
+                            uids.valueAt(i));
+                    proto.end(etoken);
+                }
+                proto.end(ctoken);
+            }
+
+        }
+
+        if (!badProcesses.getMap().isEmpty()) {
+            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = badProcesses.getMap();
+            final int processCount = pmap.size();
+            for (int ip = 0; ip < processCount; ip++) {
+                final long btoken = proto.start(AppErrorsProto.BAD_PROCESSES);
+                final String pname = pmap.keyAt(ip);
+                final SparseArray<BadProcessInfo> uids = pmap.valueAt(ip);
+                final int uidCount = uids.size();
+
+                proto.write(AppErrorsProto.BadProcess.PROCESS_NAME, pname);
+                for (int i = 0; i < uidCount; i++) {
+                    final int puid = uids.keyAt(i);
+                    final ProcessRecord r = mService.getProcessNames().get(pname, puid);
+                    if (dumpPackage != null && (r == null
+                            || !r.pkgList.containsKey(dumpPackage))) {
+                        continue;
+                    }
+                    final BadProcessInfo info = uids.valueAt(i);
+                    final long etoken = proto.start(AppErrorsProto.BadProcess.ENTRIES);
+                    proto.write(AppErrorsProto.BadProcess.Entry.UID, puid);
+                    proto.write(AppErrorsProto.BadProcess.Entry.CRASHED_AT_MS, info.time);
+                    proto.write(AppErrorsProto.BadProcess.Entry.SHORT_MSG, info.shortMsg);
+                    proto.write(AppErrorsProto.BadProcess.Entry.LONG_MSG, info.longMsg);
+                    proto.write(AppErrorsProto.BadProcess.Entry.STACK, info.stack);
+                    proto.end(etoken);
+                }
+                proto.end(btoken);
+            }
+        }
+
+        proto.end(token);
     }
 
     boolean dumpLocked(FileDescriptor fd, PrintWriter pw, boolean needSep, String dumpPackage) {
@@ -267,9 +271,10 @@
             }
         }
 
-        if (!mBadProcesses.getMap().isEmpty()) {
+        final ProcessMap<BadProcessInfo> badProcesses = mBadProcesses;
+        if (!badProcesses.getMap().isEmpty()) {
             boolean printed = false;
-            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = mBadProcesses.getMap();
+            final ArrayMap<String, SparseArray<BadProcessInfo>> pmap = badProcesses.getMap();
             final int processCount = pmap.size();
             for (int ip = 0; ip < processCount; ip++) {
                 final String pname = pmap.keyAt(ip);
@@ -322,14 +327,25 @@
     }
 
     boolean isBadProcess(final String processName, final int uid) {
-        synchronized (mBadProcesses) {
-            return mBadProcesses.get(processName, uid) != null;
-        }
+        // NO LOCKING for the simple lookup
+        return mBadProcesses.get(processName, uid) != null;
     }
 
     void clearBadProcess(final String processName, final int uid) {
-        synchronized (mBadProcesses) {
-            mBadProcesses.remove(processName, uid);
+        synchronized (mBadProcessLock) {
+            final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
+            badProcesses.putAll(mBadProcesses);
+            badProcesses.remove(processName, uid);
+            mBadProcesses = badProcesses;
+        }
+    }
+
+    void markBadProcess(final String processName, final int uid, BadProcessInfo info) {
+        synchronized (mBadProcessLock) {
+            final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
+            badProcesses.putAll(mBadProcesses);
+            badProcesses.put(processName, uid, info);
+            mBadProcesses = badProcesses;
         }
     }
 
@@ -813,11 +829,9 @@
                         app.processName);
                 if (!app.isolated) {
                     // XXX We don't have a way to mark isolated processes
-                    // as bad, since they don't have a peristent identity.
-                    synchronized (mBadProcesses) {
-                        mBadProcesses.put(app.processName, app.uid,
-                                new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
-                    }
+                    // as bad, since they don't have a persistent identity.
+                    markBadProcess(app.processName, app.uid,
+                            new BadProcessInfo(now, shortMsg, longMsg, stackTrace));
                     mProcessCrashTimes.remove(app.processName, app.uid);
                     mProcessCrashCounts.remove(app.processName, app.uid);
                 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 422ae68..0ab3c9e 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1097,6 +1097,8 @@
                 }
             });
         }
+        FrameworkStatsLog.write_non_chained(
+                FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
     }
 
     public void notePhoneOn() {
@@ -1402,6 +1404,8 @@
                 }
             });
         }
+        FrameworkStatsLog.write_non_chained(
+                FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
     }
 
     public void noteWifiRunning(final WorkSource ws) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 7795ed3..3d71b0a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -334,7 +334,13 @@
      */
     public void setProvNotificationVisible(boolean visible, int id, String action) {
         if (visible) {
-            Intent intent = new Intent(action);
+            // For legacy purposes, action is sent as the action + the phone ID from DcTracker.
+            // Split the string here and send the phone ID as an extra instead.
+            String[] splitAction = action.split(":");
+            Intent intent = new Intent(splitAction[0]);
+            try {
+                intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1]));
+            } catch (NumberFormatException ignored) { }
             PendingIntent pendingIntent = PendingIntent.getBroadcast(
                     mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
             showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false);
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 1129899..b5f20d7 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -36,6 +36,7 @@
 import android.net.TcpKeepalivePacketData;
 import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.TcpRepairWindow;
+import android.net.util.KeepalivePacketDataUtil;
 import android.os.Handler;
 import android.os.MessageQueue;
 import android.os.Messenger;
@@ -112,7 +113,7 @@
             throws InvalidPacketException, InvalidSocketException {
         try {
             final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd);
-            return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails);
+            return KeepalivePacketDataUtil.fromStableParcelable(tcpDetails);
         } catch (InvalidPacketException | InvalidSocketException e) {
             switchOutOfRepairMode(fd);
             throw e;
@@ -122,7 +123,7 @@
      * Switch the tcp socket to repair mode and query detail tcp information.
      *
      * @param fd the fd of socket on which to use keepalive offload.
-     * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current
+     * @return a {@link TcpKeepalivePacketDataParcelable} object for current
      * tcp/ip information.
      */
     private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd)
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
index dad6e39..08b8a8c 100644
--- a/services/core/java/com/android/server/locksettings/OWNERS
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -1,2 +1,3 @@
 jaggies@google.com
 kchyn@google.com
+rubinxu@google.com
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 5787f7c4..8d5f553 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -15,20 +15,15 @@
  */
 
 package com.android.server.locksettings;
-
 import static android.os.UserHandle.USER_SYSTEM;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.pm.UserInfo;
-import android.hardware.rebootescrow.IRebootEscrow;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.util.Slog;
 
@@ -44,7 +39,6 @@
 import java.util.Date;
 import java.util.List;
 import java.util.Locale;
-import java.util.NoSuchElementException;
 
 class RebootEscrowManager {
     private static final String TAG = "RebootEscrowManager";
@@ -116,8 +110,24 @@
     static class Injector {
         protected Context mContext;
 
+        private final RebootEscrowProviderInterface mRebootEscrowProvider;
+
         Injector(Context context) {
             mContext = context;
+            RebootEscrowProviderInterface rebootEscrowProvider = null;
+            // TODO(xunchang) add implementation for server based ror.
+            if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
+                    "server_based_ror_enabled", false)) {
+                Slog.e(TAG, "Server based ror isn't implemented yet.");
+            } else {
+                rebootEscrowProvider = new RebootEscrowProviderHalImpl();
+            }
+
+            if (rebootEscrowProvider != null && rebootEscrowProvider.hasRebootEscrowSupport()) {
+                mRebootEscrowProvider = rebootEscrowProvider;
+            } else {
+                mRebootEscrowProvider = null;
+            }
         }
 
         public Context getContext() {
@@ -128,15 +138,8 @@
             return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         }
 
-        @Nullable
-        public IRebootEscrow getRebootEscrow() {
-            try {
-                return IRebootEscrow.Stub.asInterface(ServiceManager.getService(
-                        "android.hardware.rebootescrow.IRebootEscrow/default"));
-            } catch (NoSuchElementException e) {
-                Slog.i(TAG, "Device doesn't implement RebootEscrow HAL");
-            }
-            return null;
+        public RebootEscrowProviderInterface getRebootEscrowProvider() {
+            return mRebootEscrowProvider;
         }
 
         public int getBootCount() {
@@ -210,45 +213,18 @@
     }
 
     private RebootEscrowKey getAndClearRebootEscrowKey() {
-        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
-        if (rebootEscrow == null) {
-            Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable");
+        RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+        if (rebootEscrowProvider == null) {
+            Slog.w(TAG,
+                    "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
             return null;
         }
 
-        try {
-            byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
-            if (escrowKeyBytes == null) {
-                Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key");
-                return null;
-            } else if (escrowKeyBytes.length != 32) {
-                Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
-                        + escrowKeyBytes.length);
-                return null;
-            }
-
-            // Make sure we didn't get the null key.
-            int zero = 0;
-            for (int i = 0; i < escrowKeyBytes.length; i++) {
-                zero |= escrowKeyBytes[i];
-            }
-            if (zero == 0) {
-                Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
-                return null;
-            }
-
-            // Overwrite the existing key with the null key
-            rebootEscrow.storeKey(new byte[32]);
-
+        RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(null);
+        if (key != null) {
             mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
-            return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Could not retrieve escrow data");
-            return null;
-        } catch (ServiceSpecificException e) {
-            Slog.w(TAG, "Got service-specific exception: " + e.errorCode);
-            return null;
         }
+        return key;
     }
 
     private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey key) {
@@ -279,9 +255,9 @@
             return;
         }
 
-        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
-        if (rebootEscrow == null) {
-            Slog.w(TAG, "Reboot escrow requested, but RebootEscrow HAL is unavailable");
+        if (mInjector.getRebootEscrowProvider() == null) {
+            Slog.w(TAG,
+                    "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
             return;
         }
 
@@ -293,6 +269,7 @@
 
         final RebootEscrowData escrowData;
         try {
+            // TODO(xunchang) further wrap the escrowData with a key from keystore.
             escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion,
                     syntheticPassword);
         } catch (IOException e) {
@@ -330,18 +307,16 @@
         mRebootEscrowWanted = false;
         setRebootEscrowReady(false);
 
-        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
-        if (rebootEscrow == null) {
+
+        RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+        if (rebootEscrowProvider == null) {
+            Slog.w(TAG,
+                    "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
             return;
         }
 
         mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM);
-
-        try {
-            rebootEscrow.storeKey(new byte[32]);
-        } catch (RemoteException | ServiceSpecificException e) {
-            Slog.w(TAG, "Could not call RebootEscrow HAL to shred key");
-        }
+        rebootEscrowProvider.clearRebootEscrowKey();
 
         List<UserInfo> users = mUserManager.getUsers();
         for (UserInfo user : users) {
@@ -356,9 +331,10 @@
             return false;
         }
 
-        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
-        if (rebootEscrow == null) {
-            Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable");
+        RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+        if (rebootEscrowProvider == null) {
+            Slog.w(TAG,
+                    "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
             return false;
         }
 
@@ -372,15 +348,7 @@
             return false;
         }
 
-        boolean armedRebootEscrow = false;
-        try {
-            rebootEscrow.storeKey(escrowKey.getKeyBytes());
-            armedRebootEscrow = true;
-            Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL");
-        } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e);
-        }
-
+        boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, null);
         if (armedRebootEscrow) {
             mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
             mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
@@ -397,7 +365,7 @@
     }
 
     boolean prepareRebootEscrow() {
-        if (mInjector.getRebootEscrow() == null) {
+        if (mInjector.getRebootEscrowProvider() == null) {
             return false;
         }
 
@@ -408,7 +376,7 @@
     }
 
     boolean clearRebootEscrow() {
-        if (mInjector.getRebootEscrow() == null) {
+        if (mInjector.getRebootEscrowProvider() == null) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java
new file mode 100644
index 0000000..6c1040b
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.locksettings;
+
+import android.annotation.Nullable;
+import android.hardware.rebootescrow.IRebootEscrow;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL.
+ */
+class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface {
+    private static final String TAG = "RebootEscrowProvider";
+
+    private final Injector mInjector;
+
+    static class Injector {
+        @Nullable
+        public IRebootEscrow getRebootEscrow() {
+            try {
+                return IRebootEscrow.Stub.asInterface(ServiceManager.getService(
+                        "android.hardware.rebootescrow.IRebootEscrow/default"));
+            } catch (NoSuchElementException e) {
+                Slog.i(TAG, "Device doesn't implement RebootEscrow HAL");
+            }
+            return null;
+        }
+    }
+
+    RebootEscrowProviderHalImpl() {
+        mInjector = new Injector();
+    }
+
+    @VisibleForTesting
+    RebootEscrowProviderHalImpl(Injector injector) {
+        mInjector = injector;
+    }
+
+    @Override
+    public boolean hasRebootEscrowSupport() {
+        return mInjector.getRebootEscrow() != null;
+    }
+
+    @Override
+    public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) {
+        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+        if (rebootEscrow == null) {
+            Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable");
+            return null;
+        }
+
+        try {
+            byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
+            if (escrowKeyBytes == null) {
+                Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key");
+                return null;
+            } else if (escrowKeyBytes.length != 32) {
+                Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
+                        + escrowKeyBytes.length);
+                return null;
+            }
+
+            // Make sure we didn't get the null key.
+            int zero = 0;
+            for (int i = 0; i < escrowKeyBytes.length; i++) {
+                zero |= escrowKeyBytes[i];
+            }
+            if (zero == 0) {
+                Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
+                return null;
+            }
+
+            // Overwrite the existing key with the null key
+            rebootEscrow.storeKey(new byte[32]);
+
+            return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not retrieve escrow data");
+            return null;
+        } catch (ServiceSpecificException e) {
+            Slog.w(TAG, "Got service-specific exception: " + e.errorCode);
+            return null;
+        }
+    }
+
+    @Override
+    public void clearRebootEscrowKey() {
+        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+        if (rebootEscrow == null) {
+            return;
+        }
+
+        try {
+            rebootEscrow.storeKey(new byte[32]);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.w(TAG, "Could not call RebootEscrow HAL to shred key");
+        }
+
+    }
+
+    @Override
+    public boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey) {
+        IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+        if (rebootEscrow == null) {
+            Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable");
+            return false;
+        }
+
+        try {
+            // The HAL interface only accept 32 bytes data. And the encrypted bytes for the escrow
+            // key may exceed that limit. So we just store the raw key bytes here.
+            rebootEscrow.storeKey(escrowKey.getKeyBytes());
+            Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL");
+            return true;
+        } catch (RemoteException | ServiceSpecificException e) {
+            Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e);
+        }
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java
new file mode 100644
index 0000000..857ad5f
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java
@@ -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.
+ */
+
+package com.android.server.locksettings;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Provides APIs for {@link RebootEscrowManager} to access and manage the reboot escrow key.
+ * Implementations need to find a way to persist the key across a reboot, and securely discards the
+ * persisted copy.
+ *
+ * @hide
+ */
+public interface RebootEscrowProviderInterface {
+    /**
+     * Returns true if the secure store/discard of reboot escrow key is supported.
+     */
+    boolean hasRebootEscrowSupport();
+
+    /**
+     * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted,
+     * use the input key to decrypt the RebootEscrowKey. Returns null on failure.
+     */
+    RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey);
+
+    /**
+     * Clears the stored RebootEscrowKey.
+     */
+    void clearRebootEscrowKey();
+
+    /**
+     * Saves the given RebootEscrowKey, optionally encrypt the storage with the encryptionKey.
+     */
+    boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey);
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 525fca0..d3d998a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2274,10 +2274,24 @@
             if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) {
                 return;
             }
-            if (properties.getKeyset()
-                    .contains(SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE)) {
-                mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE);
-                mAssistants.resetDefaultAssistantsIfNecessary();
+            for (String name : properties.getKeyset()) {
+                if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) {
+                    mAssistants.resetDefaultAssistantsIfNecessary();
+                } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_PRIORITIZER.equals(name)) {
+                    String value = properties.getString(name, null);
+                    if ("true".equals(value)) {
+                        mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE);
+                    } else if ("false".equals(value)) {
+                        mAssistants.disallowAdjustmentType(Adjustment.KEY_IMPORTANCE);
+                    }
+                } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_RANKING.equals(name)) {
+                    String value = properties.getString(name, null);
+                    if ("true".equals(value)) {
+                        mAssistants.allowAdjustmentType(Adjustment.KEY_RANKING_SCORE);
+                    } else if ("false".equals(value)) {
+                        mAssistants.disallowAdjustmentType(Adjustment.KEY_RANKING_SCORE);
+                    }
+                }
             }
         };
         DeviceConfig.addOnPropertiesChangedListener(
@@ -6349,7 +6363,6 @@
         private final int mRank;
         private final int mCount;
         private final ManagedServiceInfo mListener;
-        private final long mWhen;
 
         CancelNotificationRunnable(final int callingUid, final int callingPid,
                 final String pkg, final String tag, final int id,
@@ -6369,7 +6382,6 @@
             this.mRank = rank;
             this.mCount = count;
             this.mListener = listener;
-            this.mWhen = System.currentTimeMillis();
         }
 
         @Override
@@ -6381,33 +6393,8 @@
             }
 
             synchronized (mNotificationLock) {
-                // Check to see if there is a notification in the enqueued list that hasn't had a
-                // chance to post yet.
-                List<NotificationRecord> enqueued = findEnqueuedNotificationsForCriteria(
-                        mPkg, mTag, mId, mUserId);
-                boolean repost = false;
-                if (enqueued.size() > 0) {
-                    // Found something, let's see what it was
-                    repost = true;
-                    // If all enqueues happened before this cancel then wait for them to happen,
-                    // otherwise we should let this cancel through so the next enqueue happens
-                    for (NotificationRecord r : enqueued) {
-                        if (r.mUpdateTimeMs > mWhen) {
-                            // At least one enqueue was posted after the cancel, so we're invalid
-                            Slog.i(TAG, "notification cancel ignored due to newer enqueued entry"
-                                    + "key=" + r.getSbn().getKey());
-                            return;
-                        }
-                    }
-                }
-                if (repost) {
-                    mHandler.post(this);
-                    return;
-                }
-
-                // Look for the notification in the posted list, since we already checked enqueued.
-                NotificationRecord r =
-                        findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId);
+                // Look for the notification, searching both the posted and enqueued lists.
+                NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
                 if (r != null) {
                     // The notification was found, check if it should be removed.
 
@@ -6430,10 +6417,6 @@
                     if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
                         return;
                     }
-                    if (r.getUpdateTimeMs() > mWhen) {
-                        // In this case, a post must have slipped by when this runnable reposted
-                        return;
-                    }
 
                     // Bubbled children get to stick around if the summary was manually cancelled
                     // (user removed) from systemui.
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dac2e4f..b131aff 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -347,7 +347,7 @@
         }
         final StateProvider stateProvider = command -> {
             synchronized (injector.getLock()) {
-                command.currentState(injector.getSettings().mPackages,
+                command.currentState(injector.getSettings().getPackagesLocked(),
                         injector.getUserManagerInternal().getUserInfos());
             }
         };
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 7db2319..d6400f3 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -128,12 +128,12 @@
         synchronized (mPackageManagerService.mLock) {
             // Important: the packages we need to run with ab-ota compiler-reason.
             important = PackageManagerServiceUtils.getPackagesForDexopt(
-                    mPackageManagerService.mSettings.mPackages.values(), mPackageManagerService,
-                    DEBUG_DEXOPT);
+                    mPackageManagerService.mSettings.getPackagesLocked().values(),
+                    mPackageManagerService, DEBUG_DEXOPT);
             // Remove Platform Package from A/B OTA b/160735835.
             important.removeIf(isPlatformPackage);
             // Others: we should optimize this with the (first-)boot compiler-reason.
-            others = new ArrayList<>(mPackageManagerService.mSettings.mPackages.values());
+            others = new ArrayList<>(mPackageManagerService.mSettings.getPackagesLocked().values());
             others.removeAll(important);
             others.removeIf(PackageManagerServiceUtils.REMOVE_IF_NULL_PKG);
             others.removeIf(isPlatformPackage);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9f8f6e44..9e48ddd 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -747,8 +747,8 @@
                 installerAttributionTag);
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                 mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
-                installSource, params, createdMillis, stageDir, stageCid, null, null, false, false,
-                false, false, null, SessionInfo.INVALID_ID, false, false, false,
+                installSource, params, createdMillis, 0L, stageDir, stageCid, null, null, false,
+                false, false, false, null, SessionInfo.INVALID_ID, false, false, false,
                 SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
         synchronized (mSessions) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4ab1282..2537e1b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -35,6 +35,7 @@
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 import static com.android.internal.util.XmlUtils.readBitmapAttribute;
 import static com.android.internal.util.XmlUtils.readByteArrayAttribute;
 import static com.android.internal.util.XmlUtils.readStringAttribute;
@@ -132,6 +133,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.messages.nano.SystemMessageProto;
@@ -201,6 +203,7 @@
             "installOriginatingPackageName";
     private static final String ATTR_CREATED_MILLIS = "createdMillis";
     private static final String ATTR_UPDATED_MILLIS = "updatedMillis";
+    private static final String ATTR_COMMITTED_MILLIS = "committedMillis";
     private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
     private static final String ATTR_PREPARED = "prepared";
@@ -291,6 +294,10 @@
     @GuardedBy("mLock")
     private long updatedMillis;
 
+    /** Timestamp of the time this session is committed  */
+    @GuardedBy("mLock")
+    private long committedMillis;
+
     /** Uid of the creator of this session. */
     private final int mOriginalInstallerUid;
 
@@ -625,7 +632,7 @@
             Context context, PackageManagerService pm,
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
             int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
-            SessionParams params, long createdMillis,
+            SessionParams params, long createdMillis, long committedMillis,
             File stageDir, String stageCid, InstallationFile[] files,
             ArrayMap<String, List<CertifiedChecksum>> checksums,
             boolean prepared, boolean committed, boolean destroyed, boolean sealed,
@@ -648,6 +655,7 @@
         this.params = params;
         this.createdMillis = createdMillis;
         this.updatedMillis = createdMillis;
+        this.committedMillis = committedMillis;
         this.stageDir = stageDir;
         this.stageCid = stageCid;
         this.mShouldBeSealed = sealed;
@@ -1641,6 +1649,7 @@
                 mActiveCount.incrementAndGet();
 
                 mCommitted = true;
+                committedMillis = System.currentTimeMillis();
             }
             return true;
         } catch (PackageManagerException e) {
@@ -1796,7 +1805,7 @@
 
     @Override
     public void transfer(String packageName) {
-        Objects.requireNonNull(packageName);
+        Preconditions.checkArgument(!TextUtils.isEmpty(packageName));
 
         ApplicationInfo newOwnerAppInfo = mPm.getApplicationInfo(packageName, 0, userId);
         if (newOwnerAppInfo == null) {
@@ -1822,7 +1831,7 @@
             try {
                 sealLocked();
             } catch (PackageManagerException e) {
-                throw new IllegalArgumentException("Package is not valid", e);
+                throw new IllegalStateException("Package is not valid", e);
             }
 
             mInstallerUid = newOwnerAppInfo.uid;
@@ -2963,7 +2972,8 @@
     /**
      * @return the package name of this session
      */
-    String getPackageName() {
+    @VisibleForTesting(visibility = PACKAGE)
+    public String getPackageName() {
         synchronized (mLock) {
             return mPackageName;
         }
@@ -2978,6 +2988,12 @@
         }
     }
 
+    long getCommittedMillis() {
+        synchronized (mLock) {
+            return committedMillis;
+        }
+    }
+
     String getInstallerPackageName() {
         return getInstallSource().installerPackageName;
     }
@@ -3923,6 +3939,7 @@
         pw.printPair("mInstallerUid", mInstallerUid);
         pw.printPair("createdMillis", createdMillis);
         pw.printPair("updatedMillis", updatedMillis);
+        pw.printPair("committedMillis", committedMillis);
         pw.printPair("stageDir", stageDir);
         pw.printPair("stageCid", stageCid);
         pw.println();
@@ -4099,6 +4116,7 @@
                     mInstallSource.originatingPackageName);
             out.attributeLong(null, ATTR_CREATED_MILLIS, createdMillis);
             out.attributeLong(null, ATTR_UPDATED_MILLIS, updatedMillis);
+            out.attributeLong(null, ATTR_COMMITTED_MILLIS, committedMillis);
             if (stageDir != null) {
                 writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
                         stageDir.getAbsolutePath());
@@ -4252,6 +4270,7 @@
                 readStringAttribute(in, ATTR_ORIGINATING_PACKAGE_NAME);
         final long createdMillis = in.getAttributeLong(null, ATTR_CREATED_MILLIS);
         long updatedMillis = in.getAttributeLong(null, ATTR_UPDATED_MILLIS);
+        final long committedMillis = in.getAttributeLong(null, ATTR_COMMITTED_MILLIS, 0L);
         final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
         final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
@@ -4395,8 +4414,9 @@
                 installOriginatingPackageName, installerPackageName, installerAttributionTag);
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 installerThread, stagingManager, sessionId, userId, installerUid,
-                installSource, params, createdMillis, stageDir, stageCid, fileArray, checksums,
-                prepared, committed, destroyed, sealed, childSessionIdsArray, parentSessionId,
-                isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
+                installSource, params, createdMillis, committedMillis, stageDir, stageCid,
+                fileArray, checksums, prepared, committed, destroyed, sealed, childSessionIdsArray,
+                parentSessionId, isReady, isFailed, isApplied, stagedSessionErrorCode,
+                stagedSessionErrorMessage);
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d14baf5..282fb58 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -260,7 +260,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Debug;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -5529,8 +5528,7 @@
             // to the same user is not sufficient
             enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false,
                     !isRecentsAccessingChildProfiles(Binder.getCallingUid(), userId),
-                    "MATCH_ANY_USER flag requires INTERACT_ACROSS_USERS permission at "
-                    + Debug.getCallers(5));
+                    "MATCH_ANY_USER flag requires INTERACT_ACROSS_USERS permission");
         } else if ((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0 && isCallerSystemUser
                 && mUserManager.hasManagedProfile(UserHandle.USER_SYSTEM)) {
             // If the caller wants all packages and has a restricted profile associated with it,
@@ -17692,12 +17690,12 @@
             final SparseArray<int[]> newBroadcastAllowList;
             final String codePath;
             synchronized (mLock) {
-                final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+                final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
                 if (ps == null) {
                     return;
                 }
                 newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
-                        ps, mInstalledUserIds, mSettings.mPackages);
+                        ps, mInstalledUserIds, mSettings.getPackagesLocked());
                 codePath = ps.getPathString();
             }
             Bundle extras = new Bundle();
@@ -17715,12 +17713,12 @@
         public void onPackageUnstartable(int reason) {
             final SparseArray<int[]> newBroadcastAllowList;
             synchronized (mLock) {
-                final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+                final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
                 if (ps == null) {
                     return;
                 }
                 newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
-                        ps, mInstalledUserIds, mSettings.mPackages);
+                        ps, mInstalledUserIds, mSettings.getPackagesLocked());
             }
             Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17737,12 +17735,12 @@
         public void onPackageStartable() {
             final SparseArray<int[]> newBroadcastAllowList;
             synchronized (mLock) {
-                final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+                final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
                 if (ps == null) {
                     return;
                 }
                 newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
-                        ps, mInstalledUserIds, mSettings.mPackages);
+                        ps, mInstalledUserIds, mSettings.getPackagesLocked());
             }
             Bundle extras = new Bundle();
             extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17768,7 +17766,7 @@
         public void onPackageLoadingProgressChanged(float progress) {
             final PackageSetting ps;
             synchronized (mLock) {
-                ps = mSettings.mPackages.get(mPackageName);
+                ps = mSettings.getPackageLPr(mPackageName);
             }
             if (ps == null) {
                 return;
@@ -17791,7 +17789,7 @@
         public void onHealthStatus(int storageId, int status) throws RemoteException {
             final PackageSetting ps;
             synchronized (mLock) {
-                ps = mSettings.mPackages.get(mPackageName);
+                ps = mSettings.getPackageLPr(mPackageName);
             }
             if (ps == null) {
                 return;
@@ -17804,7 +17802,7 @@
             int userId) {
         final PackageSetting ps;
         synchronized (mLock) {
-            ps = mSettings.mPackages.get(packageName);
+            ps = mSettings.getPackageLPr(packageName);
             if (ps == null) {
                 Slog.w(TAG, "Failed to get package setting. Package " + packageName
                         + " is not installed");
@@ -20730,6 +20728,11 @@
     @GuardedBy("mLock")
     void clearIntentFilterVerificationsLPw(String packageName, int userId,
             boolean alsoResetStatus) {
+        if (SystemConfig.getInstance().getLinkedApps().contains(packageName)) {
+            // Nope, need to preserve the system configuration approval for this app
+            return;
+        }
+
         if (userId == UserHandle.USER_ALL) {
             if (mSettings.removeIntentFilterVerificationLPw(packageName,
                     mUserManager.getUserIds())) {
@@ -24612,7 +24615,7 @@
             // which was uninstalled while keeping its data.
             AndroidPackage dataOwnerPkg = mPackages.get(packageName);
             if (dataOwnerPkg  == null) {
-                PackageSetting ps = mSettings.mPackages.get(packageName);
+                PackageSetting ps = mSettings.getPackageLPr(packageName);
                 if (ps != null) {
                     dataOwnerPkg = ps.pkg;
                 }
@@ -26059,7 +26062,7 @@
         public void notifyPackageCrashOrAnr(@NonNull String packageName) {
             final PackageSetting ps;
             synchronized (mLock) {
-                ps = mSettings.mPackages.get(packageName);
+                ps = mSettings.getPackageLPr(packageName);
                 if (ps == null) {
                     Slog.w(TAG, "Failed notifyPackageCrash. Package " + packageName
                             + " is not installed");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2d5034e..7482ef45 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -295,6 +295,7 @@
     private final File mKernelMappingFilename;
 
     /** Map from package name to settings */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
 
     /**
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c68fe81..56fb5e8 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -537,7 +537,9 @@
         synchronized (mLock) {
             // Clear the launcher cache for this user. It will be set again next time the default
             // launcher is read from RoleManager.
-            getUserShortcutsLocked(userId).setCachedLauncher(null);
+            if (isUserLoadedLocked(userId)) {
+                getUserShortcutsLocked(userId).setCachedLauncher(null);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 85c4ab2..222874d 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -59,6 +59,7 @@
 import android.util.apk.ApkSignatureVerifier;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageHelper;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
@@ -720,7 +721,8 @@
      * </ul>
      * @throws PackageManagerException if session fails the check
      */
-    private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+    @VisibleForTesting
+    void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
             throws PackageManagerException {
         if (session.isMultiPackage()) {
             // We cannot say a parent session overlaps until we process its children
@@ -747,6 +749,13 @@
                     continue;
                 }
 
+                if (stagedSession.getCommittedMillis() > session.getCommittedMillis()) {
+                    // Ignore sessions that are committed after the provided session. When there are
+                    // overlaps between sessions, we will fail the one committed later instead of
+                    // the earlier one.
+                    continue;
+                }
+
                 // From here on, stagedSession is a parent active staged session
 
                 // Check if session is one of the active sessions
@@ -793,7 +802,8 @@
         }
     }
 
-    private void createSession(@NonNull PackageInstallerSession sessionInfo) {
+    @VisibleForTesting
+    void createSession(@NonNull PackageInstallerSession sessionInfo) {
         synchronized (mStagedSessions) {
             mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
         }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ccbf73c..225c998 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4760,13 +4760,31 @@
                 final boolean hasParent = user.profileGroupId != user.id
                         && user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID;
                 if (verbose) {
-                    pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s\n", i, user.id, user.name,
+                    final DevicePolicyManagerInternal dpm = getDevicePolicyManagerInternal();
+                    String deviceOwner = "";
+                    String profileOwner = "";
+                    if (dpm != null) {
+                        final long ident = Binder.clearCallingIdentity();
+                        try {
+                            if (dpm.getDeviceOwnerUserId() == user.id) {
+                                deviceOwner = " (device-owner)";
+                            }
+                            if (dpm.getProfileOwnerAsUser(user.id) != null) {
+                                profileOwner = " (profile-owner)";
+                            }
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
+                        }
+                    }
+                    pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s%s%s\n", i, user.id,
+                            user.name,
                             UserInfo.flagsToString(user.flags),
                             hasParent ? " (parentId=" + user.profileGroupId + ")" : "",
                             running ? " (running)" : "",
                             user.partial ? " (partial)" : "",
                             user.preCreated ? " (pre-created)" : "",
                             user.convertedFromPreCreated ? " (converted)" : "",
+                            deviceOwner, profileOwner,
                             current ? " (current)" : "");
                 } else {
                     // NOTE: the standard "list users" command is used by integration tests and
@@ -4860,6 +4878,21 @@
                     if (userInfo.convertedFromPreCreated) {
                         pw.print(" <converted>");
                     }
+                    final DevicePolicyManagerInternal dpm = getDevicePolicyManagerInternal();
+                    if (dpm != null) {
+                        final long ident = Binder.clearCallingIdentity();
+                        try {
+                            if (dpm.getDeviceOwnerUserId() == userId) {
+                                pw.print(" <device-owner>");
+                            }
+                            if (dpm.getProfileOwnerAsUser(userId) != null) {
+                                pw.print(" <profile-owner>");
+                            }
+                        } finally {
+                            Binder.restoreCallingIdentity(ident);
+                        }
+                    }
+
                     pw.println();
                     pw.print("    Type: "); pw.println(userInfo.userType);
                     pw.print("    Flags: "); pw.print(userInfo.flags); pw.print(" (");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 26915bc..6919cea 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4017,9 +4017,12 @@
             return true;
         }
 
-        // Watches handle BACK specially
+        // Watches handle BACK and hardware buttons specially
         if (mHasFeatureWatch && (keyCode == KeyEvent.KEYCODE_BACK
-                || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+                || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY
+                || keyCode == KeyEvent.KEYCODE_STEM_1
+                || keyCode == KeyEvent.KEYCODE_STEM_2
+                || keyCode == KeyEvent.KEYCODE_STEM_3)) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
index 8eb66cd..eea79f6 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
@@ -1138,6 +1138,7 @@
                     ipw.println(mLastDeviceConfigProperties.getString(key, null));
                 }
             }
+            ipw.decreaseIndent();
 
             ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get());
             ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get());
@@ -1191,7 +1192,7 @@
     }
 
     private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) {
-        if (map == null) {
+        if (map == null || map.size() == 0) {
             pw.println("N/A");
             return;
         }
diff --git a/services/core/java/com/android/server/recoverysystem/OWNERS b/services/core/java/com/android/server/recoverysystem/OWNERS
new file mode 100644
index 0000000..79ded0d
--- /dev/null
+++ b/services/core/java/com/android/server/recoverysystem/OWNERS
@@ -0,0 +1,2 @@
+rvrolyk@google.com
+zhaojiac@google.com
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index d9b6702..e12991a 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -51,6 +51,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
+import com.android.server.RescueParty;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.File;
@@ -540,7 +541,10 @@
             PackageInstaller.Session parentSession = packageInstaller.openSession(
                     parentSessionId);
 
+            List<String> packageNames = new ArrayList<>(info.getPackages().size());
             for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
+                packageNames.add(pkgRollbackInfo.getPackageName());
+
                 if (pkgRollbackInfo.isApkInApex()) {
                     // No need to issue a downgrade install request for apk-in-apex. It will
                     // be rolled back when its parent apex is downgraded.
@@ -601,6 +605,9 @@
                 parentSession.addChildSessionId(sessionId);
             }
 
+            // Clear flags.
+            RescueParty.resetDeviceConfigForPackages(packageNames);
+
             Consumer<Intent> onResult = result -> {
                 mHandler.post(() -> {
                     assertInWorkerThread();
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 8438652..8071672 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1532,8 +1532,8 @@
                 // All shared app gids are accounted together.
                 uid = LAST_SHARED_APPLICATION_GID;
                 mutateInPlace = true;
-            } else if (UserHandle.isApp(uid)) {
-                // Apps are accounted under their app id.
+            } else {
+                // Everything else is accounted under their base uid.
                 uid = UserHandle.getAppId(uid);
             }
 
@@ -3164,9 +3164,7 @@
             mAttributionTag = attributionTag;
             mUid = uid;
             mOp = op;
-            mHash = ((op.getOpCode() * 961
-                    + (attributionTag == null ? 0 : attributionTag.hashCode()) * 31
-                    + packageName.hashCode() + RANDOM_SEED) & 0x7fffffff) % 100;
+            mHash = ((packageName.hashCode() + RANDOM_SEED) & 0x7fffffff) % 100;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8d6d981..fc9753c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5664,7 +5664,7 @@
             }
 
             if (animatingRecents != null && animatingRecents == mFixedRotationLaunchingApp
-                    && animatingRecents.isVisible()) {
+                    && animatingRecents.isVisible() && animatingRecents != topRunningActivity()) {
                 // The recents activity should be going to be invisible (switch to another app or
                 // return to original top). Only clear the top launching record without finishing
                 // the transform immediately because it won't affect display orientation. And before
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index edd01eb..af9069f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -88,7 +88,7 @@
     private static final long FAILSAFE_DELAY = 1000;
     /**
      * If the recents animation is canceled before the delay since the window drawn, do not log the
-     * action because the duration is too small that may be just a mistouch,
+     * action because the duration is too small that may be just a mistouch.
      */
     private static final long LATENCY_TRACKER_LOG_DELAY_MS = 300;
 
diff --git a/services/core/xsd/device-state-config/OWNERS b/services/core/xsd/device-state-config/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/services/core/xsd/device-state-config/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd
index 50145039..94a398f 100644
--- a/services/core/xsd/device-state-config/device-state-config.xsd
+++ b/services/core/xsd/device-state-config/device-state-config.xsd
@@ -37,15 +37,21 @@
                     </xs:restriction>
                 </xs:simpleType>
             </xs:element>
-            <xs:element name="name" type="xs:string" minOccurs="0" />
+            <xs:element name="name" type="xs:string" minOccurs="0">
+                <xs:annotation name="nullable" />
+            </xs:element>
             <xs:element name="conditions" type="conditions" />
         </xs:sequence>
     </xs:complexType>
 
     <xs:complexType name="conditions">
         <xs:sequence>
-            <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0" />
-            <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded" />
+            <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0">
+                <xs:annotation name="nullable" />
+            </xs:element>
+            <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation name="nullable" />
+            </xs:element>
         </xs:sequence>
     </xs:complexType>
 
@@ -66,12 +72,20 @@
     <xs:complexType name="numericRange">
         <xs:sequence>
             <xs:choice minOccurs="0">
-                <xs:element name="min" type="xs:decimal" />
-                <xs:element name="min-inclusive" type="xs:decimal" />
+                <xs:element name="min" type="xs:decimal">
+                    <xs:annotation name="nullable" />
+                </xs:element>
+                <xs:element name="min-inclusive" type="xs:decimal">
+                    <xs:annotation name="nullable" />
+                </xs:element>
             </xs:choice>
             <xs:choice minOccurs="0">
-                <xs:element name="max" type="xs:decimal" />
-                <xs:element name="max-inclusive" type="xs:decimal"/>
+                <xs:element name="max" type="xs:decimal">
+                    <xs:annotation name="nullable" />
+                </xs:element>
+                <xs:element name="max-inclusive" type="xs:decimal">
+                    <xs:annotation name="nullable" />
+                </xs:element>
             </xs:choice>
         </xs:sequence>
     </xs:complexType>
diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt
index b396af0..08fccf8 100644
--- a/services/core/xsd/device-state-config/schema/current.txt
+++ b/services/core/xsd/device-state-config/schema/current.txt
@@ -3,19 +3,19 @@
 
   public class Conditions {
     ctor public Conditions();
-    method public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch();
-    method public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor();
-    method public void setLidSwitch(com.android.server.policy.devicestate.config.LidSwitchCondition);
+    method @Nullable public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch();
+    method @Nullable public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor();
+    method public void setLidSwitch(@Nullable com.android.server.policy.devicestate.config.LidSwitchCondition);
   }
 
   public class DeviceState {
     ctor public DeviceState();
     method public com.android.server.policy.devicestate.config.Conditions getConditions();
     method public java.math.BigInteger getIdentifier();
-    method public String getName();
+    method @Nullable public String getName();
     method public void setConditions(com.android.server.policy.devicestate.config.Conditions);
     method public void setIdentifier(java.math.BigInteger);
-    method public void setName(String);
+    method public void setName(@Nullable String);
   }
 
   public class DeviceStateConfig {
@@ -31,14 +31,14 @@
 
   public class NumericRange {
     ctor public NumericRange();
-    method public java.math.BigDecimal getMaxInclusive_optional();
-    method public java.math.BigDecimal getMax_optional();
-    method public java.math.BigDecimal getMinInclusive_optional();
-    method public java.math.BigDecimal getMin_optional();
-    method public void setMaxInclusive_optional(java.math.BigDecimal);
-    method public void setMax_optional(java.math.BigDecimal);
-    method public void setMinInclusive_optional(java.math.BigDecimal);
-    method public void setMin_optional(java.math.BigDecimal);
+    method @Nullable public java.math.BigDecimal getMaxInclusive_optional();
+    method @Nullable public java.math.BigDecimal getMax_optional();
+    method @Nullable public java.math.BigDecimal getMinInclusive_optional();
+    method @Nullable public java.math.BigDecimal getMin_optional();
+    method public void setMaxInclusive_optional(@Nullable java.math.BigDecimal);
+    method public void setMax_optional(@Nullable java.math.BigDecimal);
+    method public void setMinInclusive_optional(@Nullable java.math.BigDecimal);
+    method public void setMin_optional(@Nullable java.math.BigDecimal);
   }
 
   public class SensorCondition {
diff --git a/services/core/xsd/display-device-config/OWNERS b/services/core/xsd/display-device-config/OWNERS
new file mode 100644
index 0000000..20b75be
--- /dev/null
+++ b/services/core/xsd/display-device-config/OWNERS
@@ -0,0 +1,3 @@
+include /services/core/java/com/android/server/display/OWNERS
+
+flc@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index 31ba199..c766ca0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -16,14 +16,15 @@
 
 package com.android.server.devicepolicy;
 
+import android.annotation.UserIdInt;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.os.FileUtils;
 import android.os.PersistableBundle;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
 import android.util.Slog;
 import android.util.TypedXmlPullParser;
 import android.util.TypedXmlSerializer;
@@ -77,13 +78,14 @@
     private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
             "device-provisioning-config-applied";
     private static final String ATTR_DEVICE_PAIRED = "device-paired";
+
     private static final String TAG = DevicePolicyManagerService.LOG_TAG;
     private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE
 
     int mFailedPasswordAttempts = 0;
     boolean mPasswordValidAtLastCheckpoint = true;
 
-    int mUserHandle;
+    final @UserIdInt int mUserId;
     int mPasswordOwner = -1;
     long mLastMaximumTimeToLock = -1;
     boolean mUserSetupComplete = false;
@@ -144,8 +146,8 @@
     // apps were suspended or unsuspended.
     boolean mAppsSuspended = false;
 
-    DevicePolicyData(int userHandle) {
-        mUserHandle = userHandle;
+    DevicePolicyData(@UserIdInt int userId) {
+        mUserId = userId;
     }
 
     /**
@@ -156,7 +158,7 @@
         try {
             File chooseForWrite = file.chooseForWrite();
             if (VERBOSE_LOG) {
-                Slog.v(TAG, "Storing data for user " + policyData.mUserHandle + " on "
+                Slog.v(TAG, "Storing data for user " + policyData.mUserId + " on "
                         + chooseForWrite);
             }
             stream = new FileOutputStream(chooseForWrite, false);
@@ -365,7 +367,7 @@
         FileInputStream stream = null;
         File file = journaledFile.chooseForRead();
         if (VERBOSE_LOG) {
-            Slog.v(TAG, "Loading data for user " + policy.mUserHandle + " from " + file);
+            Slog.v(TAG, "Loading data for user " + policy.mUserId + " from " + file);
         }
         boolean needsRewrite = false;
         try {
@@ -556,4 +558,37 @@
             }
         }
     }
+
+    void dump(IndentingPrintWriter pw) {
+        pw.println();
+        pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: "
+                + mUserProvisioningState + "):");
+        final int n = mAdminList.size();
+        for (int i = 0; i < n; i++) {
+            ActiveAdmin ap = mAdminList.get(i);
+            if (ap != null) {
+                pw.increaseIndent();
+                pw.print(ap.info.getComponent().flattenToShortString());
+                pw.println(":");
+                pw.increaseIndent();
+                ap.dump(pw);
+                pw.decreaseIndent();
+                pw.decreaseIndent();
+            }
+        }
+        if (!mRemovingAdmins.isEmpty()) {
+            pw.increaseIndent();
+            pw.println("Removing Device Admins (User " + mUserId + "): " + mRemovingAdmins);
+            pw.decreaseIndent();
+        }
+        pw.println();
+        pw.increaseIndent();
+        pw.print("mPasswordOwner="); pw.println(mPasswordOwner);
+        pw.print("mUserControlDisabledPackages=");
+        pw.println(mUserControlDisabledPackages);
+        pw.print("mAppsSuspended="); pw.println(mAppsSuspended);
+        pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete);
+        pw.print("mAffiliationIds="); pw.println(mAffiliationIds);
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d35d806..2df58cc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -215,7 +215,6 @@
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.Process;
-import android.os.RecoverySystem;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -245,7 +244,6 @@
 import android.security.keystore.AttestationUtils;
 import android.security.keystore.KeyGenParameterSpec;
 import android.security.keystore.ParcelableKeyGenParameterSpec;
-import android.service.persistentdata.PersistentDataBlockManager;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
@@ -940,7 +938,7 @@
 
             // Persist updates if the removed package was an admin or delegate.
             if (removedAdmin || removedDelegate) {
-                saveSettingsLocked(policy.mUserHandle);
+                saveSettingsLocked(policy.mUserId);
             }
         }
         if (removedAdmin) {
@@ -1026,6 +1024,25 @@
         mSafetyChecker = new OneTimeSafetyChecker(this, operation, safe);
     }
 
+    // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+    @Override
+    public void factoryReset(String reason) {
+        Preconditions.checkCallAuthorization(
+                hasCallingOrSelfPermission(permission.MASTER_CLEAR));
+        Slog.w(LOG_TAG, "factoryReset(): " + reason);
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            FactoryResetter.factoryReset(mContext, /* shutdown= */ false, reason,
+                    /* force= */ false, /* wipeEuicc= */ false, /* wipeAdoptableStorage= */ false,
+                    /* wipeFactoryResetProtection= */ false);
+        } catch (IOException e) {
+            // Shouldn't happen.
+            Slog.wtf(LOG_TAG, "Could not factory reset", e);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     /**
      * Unit test will subclass it to inject mocks.
      */
@@ -1276,8 +1293,10 @@
         }
 
         void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
-                boolean wipeEuicc) throws IOException {
-            RecoverySystem.rebootWipeUserData(mContext, shutdown, reason, force, wipeEuicc);
+                boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+                        throws IOException {
+            FactoryResetter.factoryReset(mContext, shutdown, reason, force, wipeEuicc,
+                    wipeExtRequested, wipeResetProtectionData);
         }
 
         boolean systemPropertiesGetBoolean(String key, boolean def) {
@@ -5905,25 +5924,26 @@
      * @return {@code true} if the calling process is the credential management app.
      */
     private boolean isCredentialManagementApp(CallerIdentity caller, String alias) {
-        // Should include alias in authentication policy
-        try (KeyChainConnection connection = KeyChain.bindAsUser(mContext,
-                caller.getUserHandle())) {
-            // The policy will be null if there is no credential management app
-            AppUriAuthenticationPolicy policy =
-                    connection.getService().getCredentialManagementAppPolicy();
-            if (policy == null || policy.getAppAndUriMappings().isEmpty()
-                    || !containsAlias(policy, alias)) {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            // Should include alias in authentication policy
+            try (KeyChainConnection connection = KeyChain.bindAsUser(mContext,
+                    caller.getUserHandle())) {
+                // The policy will be null if there is no credential management app
+                AppUriAuthenticationPolicy policy =
+                        connection.getService().getCredentialManagementAppPolicy();
+                if (policy == null || policy.getAppAndUriMappings().isEmpty()
+                        || !containsAlias(policy, alias)) {
+                    return false;
+                }
+            } catch (RemoteException | InterruptedException e) {
                 return false;
             }
-        } catch (RemoteException | InterruptedException e) {
-            return false;
-        }
 
-        AppOpsManager appOpsManager = mInjector.getAppOpsManager();
-        return appOpsManager != null
-                ? appOpsManager.noteOpNoThrow(AppOpsManager.OP_MANAGE_CREDENTIALS, caller.getUid(),
-                caller.getPackageName(), null, null) == AppOpsManager.MODE_ALLOWED
-                : false;
+            AppOpsManager appOpsManager = mInjector.getAppOpsManager();
+            if (appOpsManager == null) return false;
+            return appOpsManager.noteOpNoThrow(AppOpsManager.OP_MANAGE_CREDENTIALS, caller.getUid(),
+                    caller.getPackageName(), null, null) == AppOpsManager.MODE_ALLOWED;
+        });
     }
 
     private static boolean containsAlias(AppUriAuthenticationPolicy policy, String alias) {
@@ -6073,17 +6093,14 @@
                         caller.getUserId()));
     }
 
-    private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
+    private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc,
+            boolean wipeResetProtectionData) {
         wtfIfInLock();
         boolean success = false;
         try {
-            if (wipeExtRequested) {
-                StorageManager sm = (StorageManager) mContext.getSystemService(
-                    Context.STORAGE_SERVICE);
-                sm.wipeAdoptableDisks();
-            }
             mInjector.recoverySystemRebootWipeUserData(
-                /*shutdown=*/ false, reason, /*force=*/ true, /*wipeEuicc=*/ wipeEuicc);
+                    /* shutdown= */ false, reason, /* force= */ true, /* wipeEuicc= */ wipeEuicc,
+                    wipeExtRequested, wipeResetProtectionData);
             success = true;
         } catch (IOException | SecurityException e) {
             Slog.w(LOG_TAG, "Failed requesting data wipe", e);
@@ -6095,9 +6112,8 @@
     private void forceWipeUser(int userId, String wipeReasonForUser, boolean wipeSilently) {
         boolean success = false;
         try {
-            IActivityManager am = mInjector.getIActivityManager();
-            if (am.getCurrentUser().id == userId) {
-                am.switchUser(UserHandle.USER_SYSTEM);
+            if (getCurrentForegroundUser() == userId) {
+                mInjector.getIActivityManager().switchUser(UserHandle.USER_SYSTEM);
             }
 
             success = mUserManagerInternal.removeUserEvenWhenDisallowed(userId);
@@ -6230,22 +6246,12 @@
                         + " restriction is set for user " + userId);
             }
 
-            if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
-                PersistentDataBlockManager manager = (PersistentDataBlockManager)
-                        mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-                if (manager != null) {
-                    manager.wipe();
-                }
-            }
-
-            // TODO If split user is enabled and the device owner is set in the primary user
-            // (rather than system), we should probably trigger factory reset. Current code just
-            // removes that user (but still clears FRP...)
             if (userId == UserHandle.USER_SYSTEM) {
-                forceWipeDeviceNoLock(/*wipeExtRequested=*/ (
-                        flags & WIPE_EXTERNAL_STORAGE) != 0,
+                forceWipeDeviceNoLock(
+                        (flags & WIPE_EXTERNAL_STORAGE) != 0,
                         internalReason,
-                        /*wipeEuicc=*/ (flags & WIPE_EUICC) != 0);
+                        (flags & WIPE_EUICC) != 0,
+                        (flags & WIPE_RESET_PROTECTION_DATA) != 0);
             } else {
                 forceWipeUser(userId, wipeReasonForUser, (flags & WIPE_SILENTLY) != 0);
             }
@@ -7571,9 +7577,15 @@
             Slog.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId);
 
             if (mInjector.userManagerIsHeadlessSystemUserMode()) {
-                Slog.i(LOG_TAG, "manageUser: " + admin + " on user " + userId);
-
-                manageUser(admin, admin, caller.getUserId(), null);
+                int currentForegroundUser = getCurrentForegroundUser();
+                Slog.i(LOG_TAG, "setDeviceOwner(): setting " + admin
+                        + " as profile owner on user " + currentForegroundUser);
+                // Sets profile owner on current foreground user since
+                // the human user will complete the DO setup workflow from there.
+                mInjector.binderWithCleanCallingIdentity(() ->
+                        manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
+                                /* managedUser= */ currentForegroundUser,
+                                /* adminExtras= */ null));
             }
             return true;
         }
@@ -8558,16 +8570,19 @@
      * permission.
      */
     private void enforceCanSetDeviceOwnerLocked(CallerIdentity caller,
-            @Nullable ComponentName owner, @UserIdInt int userId) {
+            @Nullable ComponentName owner, @UserIdInt int deviceOwnerUserId) {
         if (!isAdb(caller)) {
             Preconditions.checkCallAuthorization(
                     hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
         }
 
-        final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner, userId,
-                isAdb(caller), hasIncompatibleAccountsOrNonAdbNoLock(caller, userId, owner));
+        final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner,
+                /* deviceOwnerUserId= */ deviceOwnerUserId, /* callingUserId*/ caller.getUserId(),
+                isAdb(caller),
+                hasIncompatibleAccountsOrNonAdbNoLock(caller, deviceOwnerUserId, owner));
         if (code != CODE_OK) {
-            throw new IllegalStateException(computeProvisioningErrorString(code, userId));
+            throw new IllegalStateException(
+                    computeProvisioningErrorString(code, deviceOwnerUserId));
         }
     }
 
@@ -8695,6 +8710,15 @@
         return UserHandle.isSameApp(caller.getUid(), Process.SHELL_UID);
     }
 
+    private @UserIdInt int getCurrentForegroundUser() {
+        try {
+            return mInjector.getIActivityManager().getCurrentUser().id;
+        } catch (RemoteException e) {
+            Slog.wtf(LOG_TAG, "cannot get current user");
+        }
+        return UserHandle.USER_NULL;
+    }
+
     protected int getProfileParentId(int userHandle) {
         return mInjector.binderWithCleanCallingIdentity(() -> {
             UserInfo parentUser = mUserManager.getProfileParent(userHandle);
@@ -8746,37 +8770,7 @@
         int userCount = mUserData.size();
         for (int u = 0; u < userCount; u++) {
             DevicePolicyData policy = getUserData(mUserData.keyAt(u));
-            pw.println();
-            pw.println("Enabled Device Admins (User " + policy.mUserHandle
-                    + ", provisioningState: " + policy.mUserProvisioningState + "):");
-            final int n = policy.mAdminList.size();
-            for (int i = 0; i < n; i++) {
-                ActiveAdmin ap = policy.mAdminList.get(i);
-                if (ap != null) {
-                    pw.increaseIndent();
-                    pw.print(ap.info.getComponent().flattenToShortString());
-                    pw.println(":");
-                    pw.increaseIndent();
-                    ap.dump(pw);
-                    pw.decreaseIndent();
-                    pw.decreaseIndent();
-                }
-            }
-            if (!policy.mRemovingAdmins.isEmpty()) {
-                pw.increaseIndent();
-                pw.println("Removing Device Admins (User " + policy.mUserHandle + "): "
-                        + policy.mRemovingAdmins);
-                pw.decreaseIndent();
-            }
-            pw.println();
-            pw.increaseIndent();
-            pw.print("mPasswordOwner="); pw.println(policy.mPasswordOwner);
-            pw.print("mUserControlDisabledPackages=");
-            pw.println(policy.mUserControlDisabledPackages);
-            pw.print("mAppsSuspended="); pw.println(policy.mAppsSuspended);
-            pw.print("mUserSetupComplete="); pw.println(policy.mUserSetupComplete);
-            pw.print("mAffiliationIds="); pw.println(policy.mAffiliationIds);
-            pw.decreaseIndent();
+            policy.dump(pw);
         }
     }
 
@@ -9636,7 +9630,7 @@
 
         final long id = mInjector.binderClearCallingIdentity();
         try {
-            manageUser(admin, profileOwner, userHandle, adminExtras);
+            manageUserUnchecked(admin, profileOwner, userHandle, adminExtras);
 
             if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -9657,43 +9651,34 @@
         }
     }
 
-    private void manageUser(ComponentName admin, ComponentName profileOwner,
+    private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner,
             @UserIdInt int userId, PersistableBundle adminExtras) {
-        // Check for permission
-        final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(canManageUsers(caller));
-        Preconditions.checkCallAuthorization(
-                hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
-        mInjector.binderWithCleanCallingIdentity(() ->
-                    manageUserNoCheck(admin, profileOwner, userId, adminExtras));
-    }
-
-    private void manageUserNoCheck(ComponentName admin, ComponentName profileOwner,
-            int user, PersistableBundle adminExtras) {
-
         final String adminPkg = admin.getPackageName();
         try {
             // Install the profile owner if not present.
-            if (!mIPackageManager.isPackageAvailable(adminPkg, user)) {
-                mIPackageManager.installExistingPackageAsUser(adminPkg, user,
+            if (!mIPackageManager.isPackageAvailable(adminPkg, userId)) {
+                mIPackageManager.installExistingPackageAsUser(adminPkg, userId,
                         PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS,
-                        PackageManager.INSTALL_REASON_POLICY, null);
+                        PackageManager.INSTALL_REASON_POLICY,
+                        /* allowlistedRestrictedPermissions= */ null);
             }
         } catch (RemoteException e) {
             // Does not happen, same process
+            Slog.wtf(LOG_TAG, String.format("Failed to install admin package %s for user %d",
+                    adminPkg, userId), e);
         }
 
         // Set admin.
-        setActiveAdmin(profileOwner, true, user);
+        setActiveAdmin(profileOwner, /* refreshing= */ true, userId);
         final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
-        setProfileOwner(profileOwner, ownerName, user);
+        setProfileOwner(profileOwner, ownerName, userId);
 
         synchronized (getLockObject()) {
-            DevicePolicyData policyData = getUserData(user);
+            DevicePolicyData policyData = getUserData(userId);
             policyData.mInitBundle = adminExtras;
             policyData.mAdminBroadcastPending = true;
 
-            saveSettingsLocked(user);
+            saveSettingsLocked(userId);
         }
     }
 
@@ -11780,8 +11765,13 @@
         }
 
         @Override
-        public ComponentName getProfileOwnerAsUser(int userHandle) {
-            return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
+        public ComponentName getProfileOwnerAsUser(@UserIdInt int userId) {
+            return DevicePolicyManagerService.this.getProfileOwnerAsUser(userId);
+        }
+
+        @Override
+        public int getDeviceOwnerUserId() {
+            return DevicePolicyManagerService.this.getDeviceOwnerUserId();
         }
 
         @Override
@@ -12322,7 +12312,7 @@
      * except for adb command if no accounts or additional users are present on the device.
      */
     private int checkDeviceOwnerProvisioningPreConditionLocked(@Nullable ComponentName owner,
-            @UserIdInt int deviceOwnerUserId, boolean isAdb,
+            @UserIdInt int deviceOwnerUserId, @UserIdInt int callingUserId, boolean isAdb,
             boolean hasIncompatibleAccountsOrNonAdb) {
         if (mOwners.hasDeviceOwner()) {
             return CODE_HAS_DEVICE_OWNER;
@@ -12338,6 +12328,15 @@
         if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
             return CODE_HAS_PAIRED;
         }
+
+        if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+            if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
+                Slog.e(LOG_TAG, "In headless system user mode, "
+                        + "device owner can only be set on headless system user.");
+                return CODE_NOT_SYSTEM_USER;
+            }
+        }
+
         // TODO (b/137101239): clean up split system user codes
         if (isAdb) {
             // If shell command runs after user setup completed check device status. Otherwise, OK.
@@ -12349,6 +12348,15 @@
                         && mUserManager.getUserCount() > 1) {
                     return CODE_NONSYSTEM_USER_EXISTS;
                 }
+
+                int currentForegroundUser = getCurrentForegroundUser();
+                if (callingUserId != currentForegroundUser
+                        && mInjector.userManagerIsHeadlessSystemUserMode()
+                        && currentForegroundUser == UserHandle.USER_SYSTEM) {
+                    Slog.wtf(LOG_TAG, "In headless system user mode, "
+                            + "current user cannot be system user when setting device owner");
+                    return CODE_SYSTEM_USER;
+                }
                 if (hasIncompatibleAccountsOrNonAdb) {
                     return CODE_ACCOUNTS_NOT_EMPTY;
                 }
@@ -12380,7 +12388,7 @@
                             callingUserId, deviceOwnerUserId));
             // hasIncompatibleAccountsOrNonAdb doesn't matter since the caller is not adb.
             return checkDeviceOwnerProvisioningPreConditionLocked(/* owner unknown */ null,
-                    deviceOwnerUserId, /* isAdb= */ false,
+                    deviceOwnerUserId, callingUserId, /* isAdb= */ false,
                     /* hasIncompatibleAccountsOrNonAdb=*/ true);
         }
     }
@@ -14919,8 +14927,9 @@
     }
 
     private boolean isLockTaskFeatureEnabled(int lockTaskFeature) throws RemoteException {
+        //TODO(b/175285301): Explicitly get the user's identity to check.
         int lockTaskFeatures =
-                getUserData(mInjector.getIActivityManager().getCurrentUser().id).mLockTaskFeatures;
+                getUserData(getCurrentForegroundUser()).mLockTaskFeatures;
         return (lockTaskFeatures & lockTaskFeature) == lockTaskFeature;
     }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
new file mode 100644
index 0000000..1ee6f8f
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
@@ -0,0 +1,82 @@
+/*
+ * 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 android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RecoverySystem;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.IOException;
+
+/**
+ * Entry point for "factory reset" requests.
+ */
+final class FactoryResetter {
+
+    private static final String TAG = FactoryResetter.class.getSimpleName();
+
+    // TODO(b/171603586): use an object that's constructed with a Builder instead (then update
+    // javadoc)
+    /**
+     * Factory reset the device.
+     */
+    public static void factoryReset(Context context, boolean shutdown, String reason,
+            boolean force, boolean wipeEuicc, boolean wipeAdoptableStorage,
+            boolean wipeFactoryResetProtection) throws IOException {
+        Log.i(TAG, "factoryReset(): shutdown=" + shutdown + ", force=" + force
+                + ", wipeEuicc=" + wipeEuicc + ", wipeAdoptableStorage=" + wipeAdoptableStorage
+                + ", wipeFRP=" + wipeFactoryResetProtection);
+
+        Preconditions.checkCallAuthorization(context.checkCallingOrSelfPermission(
+                android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED);
+
+        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
+            throw new SecurityException("Factory reset is not allowed for this user.");
+        }
+
+        if (wipeFactoryResetProtection) {
+            PersistentDataBlockManager manager = (PersistentDataBlockManager)
+                    context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+            if (manager != null) {
+                Log.w(TAG, "Wiping factory reset protection");
+                manager.wipe();
+            } else {
+                Log.w(TAG, "No need to wipe factory reset protection");
+            }
+        }
+
+        if (wipeAdoptableStorage) {
+            Log.w(TAG, "Wiping adoptable storage");
+            StorageManager sm = (StorageManager) context.getSystemService(
+                    Context.STORAGE_SERVICE);
+            sm.wipeAdoptableDisks();
+        }
+
+        RecoverySystem.rebootWipeUserData(context, shutdown, reason, force, wipeEuicc);
+    }
+
+    private FactoryResetter() {
+        throw new UnsupportedOperationException("Contains only static methods");
+    }
+}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index a52fe12..daf1c53 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -37,7 +37,6 @@
         "java/android/net/util/NetworkConstants.java",
         "java/android/net/IpMemoryStore.java",
         "java/android/net/NetworkMonitorManager.java",
-        "java/android/net/TcpKeepalivePacketData.java",
     ],
     sdk_version: "module_current",
     min_sdk_version: "30",
diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
deleted file mode 100644
index 4875c7c..0000000
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ /dev/null
@@ -1,268 +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.net;
-
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.system.OsConstants;
-
-import com.android.net.module.util.IpUtils;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * Represents the actual tcp keep alive packets which will be used for hardware offload.
- * @hide
- */
-public class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
-    private static final String TAG = "TcpKeepalivePacketData";
-
-    /** TCP sequence number. */
-    public final int tcpSeq;
-
-    /** TCP ACK number. */
-    public final int tcpAck;
-
-    /** TCP RCV window. */
-    public final int tcpWnd;
-
-    /** TCP RCV window scale. */
-    public final int tcpWndScale;
-
-    /** IP TOS. */
-    public final int ipTos;
-
-    /** IP TTL. */
-    public final int ipTtl;
-
-    private static final int IPV4_HEADER_LENGTH = 20;
-    private static final int IPV6_HEADER_LENGTH = 40;
-    private static final int TCP_HEADER_LENGTH = 20;
-
-    // This should only be constructed via static factory methods, such as
-    // tcpKeepalivePacket.
-    private TcpKeepalivePacketData(final TcpKeepalivePacketDataParcelable tcpDetails,
-            final byte[] data) throws InvalidPacketException, UnknownHostException {
-        super(InetAddress.getByAddress(tcpDetails.srcAddress), tcpDetails.srcPort,
-                InetAddress.getByAddress(tcpDetails.dstAddress), tcpDetails.dstPort, data);
-        tcpSeq = tcpDetails.seq;
-        tcpAck = tcpDetails.ack;
-        // In the packet, the window is shifted right by the window scale.
-        tcpWnd = tcpDetails.rcvWnd;
-        tcpWndScale = tcpDetails.rcvWndScale;
-        ipTos = tcpDetails.tos;
-        ipTtl = tcpDetails.ttl;
-    }
-
-    private TcpKeepalivePacketData(final InetAddress srcAddress, int srcPort,
-            final InetAddress dstAddress, int dstPort, final byte[] data, int tcpSeq,
-            int tcpAck, int tcpWnd, int tcpWndScale, int ipTos, int ipTtl)
-            throws InvalidPacketException {
-        super(srcAddress, srcPort, dstAddress, dstPort, data);
-        this.tcpSeq = tcpSeq;
-        this.tcpAck = tcpAck;
-        this.tcpWnd = tcpWnd;
-        this.tcpWndScale = tcpWndScale;
-        this.ipTos = ipTos;
-        this.ipTtl = ipTtl;
-    }
-
-    /**
-     * Factory method to create tcp keepalive packet structure.
-     */
-    public static TcpKeepalivePacketData tcpKeepalivePacket(
-            TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
-        final byte[] packet;
-        try {
-            if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
-                    && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
-                    && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
-                packet = buildV4Packet(tcpDetails);
-            } else {
-                // TODO: support ipv6
-                throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
-            }
-            return new TcpKeepalivePacketData(tcpDetails, packet);
-        } catch (UnknownHostException e) {
-            throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
-        }
-
-    }
-
-    /**
-     * Build ipv4 tcp keepalive packet, not including the link-layer header.
-     */
-    // TODO : if this code is ever moved to the network stack, factorize constants with the ones
-    // over there.
-    private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
-        final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
-        ByteBuffer buf = ByteBuffer.allocate(length);
-        buf.order(ByteOrder.BIG_ENDIAN);
-        buf.put((byte) 0x45);                       // IP version and IHL
-        buf.put((byte) tcpDetails.tos);             // TOS
-        buf.putShort((short) length);
-        buf.putInt(0x00004000);                     // ID, flags=DF, offset
-        buf.put((byte) tcpDetails.ttl);             // TTL
-        buf.put((byte) OsConstants.IPPROTO_TCP);
-        final int ipChecksumOffset = buf.position();
-        buf.putShort((short) 0);                    // IP checksum
-        buf.put(tcpDetails.srcAddress);
-        buf.put(tcpDetails.dstAddress);
-        buf.putShort((short) tcpDetails.srcPort);
-        buf.putShort((short) tcpDetails.dstPort);
-        buf.putInt(tcpDetails.seq);                 // Sequence Number
-        buf.putInt(tcpDetails.ack);                 // ACK
-        buf.putShort((short) 0x5010);               // TCP length=5, flags=ACK
-        buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale));   // Window size
-        final int tcpChecksumOffset = buf.position();
-        buf.putShort((short) 0);                    // TCP checksum
-        // URG is not set therefore the urgent pointer is zero.
-        buf.putShort((short) 0);                    // Urgent pointer
-
-        buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
-        buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
-                buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
-
-        return buf.array();
-    }
-
-    // TODO: add buildV6Packet.
-
-    @Override
-    public boolean equals(@Nullable final Object o) {
-        if (!(o instanceof TcpKeepalivePacketData)) return false;
-        final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
-        final InetAddress srcAddress = getSrcAddress();
-        final InetAddress dstAddress = getDstAddress();
-        return srcAddress.equals(other.getSrcAddress())
-                && dstAddress.equals(other.getDstAddress())
-                && getSrcPort() == other.getSrcPort()
-                && getDstPort() == other.getDstPort()
-                && this.tcpAck == other.tcpAck
-                && this.tcpSeq == other.tcpSeq
-                && this.tcpWnd == other.tcpWnd
-                && this.tcpWndScale == other.tcpWndScale
-                && this.ipTos == other.ipTos
-                && this.ipTtl == other.ipTtl;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
-                tcpAck, tcpSeq, tcpWnd, tcpWndScale, ipTos, ipTtl);
-    }
-
-    /**
-     * Parcelable Implementation.
-     * Note that this object implements parcelable (and needs to keep doing this as it inherits
-     * from a class that does), but should usually be parceled as a stable parcelable using
-     * the toStableParcelable() and fromStableParcelable() methods.
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Write to parcel. */
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeString(getSrcAddress().getHostAddress());
-        out.writeString(getDstAddress().getHostAddress());
-        out.writeInt(getSrcPort());
-        out.writeInt(getDstPort());
-        out.writeByteArray(getPacket());
-        out.writeInt(tcpSeq);
-        out.writeInt(tcpAck);
-        out.writeInt(tcpWnd);
-        out.writeInt(tcpWndScale);
-        out.writeInt(ipTos);
-        out.writeInt(ipTtl);
-    }
-
-    private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
-        InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
-        InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
-        int srcPort = in.readInt();
-        int dstPort = in.readInt();
-        byte[] packet = in.createByteArray();
-        int tcpSeq = in.readInt();
-        int tcpAck = in.readInt();
-        int tcpWnd = in.readInt();
-        int tcpWndScale = in.readInt();
-        int ipTos = in.readInt();
-        int ipTtl = in.readInt();
-        return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
-                tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
-    }
-
-    /** Parcelable Creator. */
-    public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
-            new Parcelable.Creator<TcpKeepalivePacketData>() {
-                public TcpKeepalivePacketData createFromParcel(Parcel in) {
-                    try {
-                        return readFromParcel(in);
-                    } catch (InvalidPacketException e) {
-                        throw new IllegalArgumentException(
-                                "Invalid NAT-T keepalive data: " + e.getError());
-                    }
-                }
-
-                public TcpKeepalivePacketData[] newArray(int size) {
-                    return new TcpKeepalivePacketData[size];
-                }
-            };
-
-    /**
-     * Convert this TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
-     */
-    @NonNull
-    public TcpKeepalivePacketDataParcelable toStableParcelable() {
-        final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
-        final InetAddress srcAddress = getSrcAddress();
-        final InetAddress dstAddress = getDstAddress();
-        parcel.srcAddress = srcAddress.getAddress();
-        parcel.srcPort = getSrcPort();
-        parcel.dstAddress = dstAddress.getAddress();
-        parcel.dstPort = getDstPort();
-        parcel.seq = tcpSeq;
-        parcel.ack = tcpAck;
-        parcel.rcvWnd = tcpWnd;
-        parcel.rcvWndScale = tcpWndScale;
-        parcel.tos = ipTos;
-        parcel.ttl = ipTtl;
-        return parcel;
-    }
-
-    @Override
-    public String toString() {
-        return "saddr: " + getSrcAddress()
-                + " daddr: " + getDstAddress()
-                + " sport: " + getSrcPort()
-                + " dport: " + getDstPort()
-                + " seq: " + tcpSeq
-                + " ack: " + tcpAck
-                + " wnd: " + tcpWnd
-                + " wndScale: " + tcpWndScale
-                + " tos: " + ipTos
-                + " ttl: " + ipTtl;
-    }
-}
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
index 94bc1ec..b45405f 100644
--- a/services/net/java/android/net/ip/IpClientManager.java
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -21,6 +21,7 @@
 import android.net.NattKeepalivePacketData;
 import android.net.ProxyInfo;
 import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.shared.Layer2Information;
 import android.net.shared.ProvisioningConfiguration;
 import android.net.util.KeepalivePacketDataUtil;
@@ -217,9 +218,20 @@
      * Add a TCP keepalive packet filter before setting up keepalive offload.
      */
     public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+        return addKeepalivePacketFilter(slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+    }
+
+    /**
+     * Add a TCP keepalive packet filter before setting up keepalive offload.
+     * @deprecated This method is for use on pre-S platforms where TcpKeepalivePacketData is not
+     *             system API. On newer platforms use
+     *             addKeepalivePacketFilter(int, TcpKeepalivePacketData) instead.
+     */
+    @Deprecated
+    public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
         final long token = Binder.clearCallingIdentity();
         try {
-            mIpClient.addKeepalivePacketFilter(slot, pkt.toStableParcelable());
+            mIpClient.addKeepalivePacketFilter(slot, pkt);
             return true;
         } catch (RemoteException e) {
             log("Error adding Keepalive Packet Filter ", e);
diff --git a/services/net/java/android/net/util/KeepalivePacketDataUtil.java b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
index 4466ea0..6e539bb 100644
--- a/services/net/java/android/net/util/KeepalivePacketDataUtil.java
+++ b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
@@ -16,20 +16,47 @@
 
 package android.net.util;
 
+import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.InvalidPacketException;
+import android.net.KeepalivePacketData;
 import android.net.NattKeepalivePacketData;
 import android.net.NattKeepalivePacketDataParcelable;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.os.Build;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.IpUtils;
 
 import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
-/** @hide */
+/**
+ * Utility class to convert to/from keepalive data parcelables.
+ *
+ * TODO: move to networkstack-client library when it is moved to frameworks/libs/net.
+ * This class cannot go into other shared libraries as it depends on NetworkStack AIDLs.
+ * @hide
+ */
 public final class KeepalivePacketDataUtil {
-     /**
-     * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+    private static final int IPV4_HEADER_LENGTH = 20;
+    private static final int IPV6_HEADER_LENGTH = 40;
+    private static final int TCP_HEADER_LENGTH = 20;
+
+    private static final String TAG = KeepalivePacketDataUtil.class.getSimpleName();
+
+    /**
+     * Convert a NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
      */
     @NonNull
     public static NattKeepalivePacketDataParcelable toStableParcelable(
-            NattKeepalivePacketData pkt) {
+            @NonNull NattKeepalivePacketData pkt) {
         final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
         final InetAddress srcAddress = pkt.getSrcAddress();
         final InetAddress dstAddress = pkt.getDstAddress();
@@ -39,4 +66,158 @@
         parcel.dstPort = pkt.getDstPort();
         return parcel;
     }
+
+    /**
+     * Convert a TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
+     */
+    @NonNull
+    public static TcpKeepalivePacketDataParcelable toStableParcelable(
+            @NonNull TcpKeepalivePacketData pkt) {
+        final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+        final InetAddress srcAddress = pkt.getSrcAddress();
+        final InetAddress dstAddress = pkt.getDstAddress();
+        parcel.srcAddress = srcAddress.getAddress();
+        parcel.srcPort = pkt.getSrcPort();
+        parcel.dstAddress = dstAddress.getAddress();
+        parcel.dstPort = pkt.getDstPort();
+        parcel.seq = pkt.tcpSeq;
+        parcel.ack = pkt.tcpAck;
+        parcel.rcvWnd = pkt.tcpWindow;
+        parcel.rcvWndScale = pkt.tcpWindowScale;
+        parcel.tos = pkt.ipTos;
+        parcel.ttl = pkt.ipTtl;
+        return parcel;
+    }
+
+    /**
+     * Factory method to create tcp keepalive packet structure.
+     * @hide
+     */
+    public static TcpKeepalivePacketData fromStableParcelable(
+            TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
+        final byte[] packet;
+        try {
+            if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
+                    && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
+                    && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
+                packet = buildV4Packet(tcpDetails);
+            } else {
+                // TODO: support ipv6
+                throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+            }
+            return new TcpKeepalivePacketData(
+                    InetAddress.getByAddress(tcpDetails.srcAddress),
+                    tcpDetails.srcPort,
+                    InetAddress.getByAddress(tcpDetails.dstAddress),
+                    tcpDetails.dstPort,
+                    packet,
+                    tcpDetails.seq, tcpDetails.ack, tcpDetails.rcvWnd, tcpDetails.rcvWndScale,
+                    tcpDetails.tos, tcpDetails.ttl);
+        } catch (UnknownHostException e) {
+            throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+        }
+
+    }
+
+    /**
+     * Build ipv4 tcp keepalive packet, not including the link-layer header.
+     */
+    // TODO : if this code is ever moved to the network stack, factorize constants with the ones
+    // over there.
+    private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
+        final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
+        ByteBuffer buf = ByteBuffer.allocate(length);
+        buf.order(ByteOrder.BIG_ENDIAN);
+        buf.put((byte) 0x45);                       // IP version and IHL
+        buf.put((byte) tcpDetails.tos);             // TOS
+        buf.putShort((short) length);
+        buf.putInt(0x00004000);                     // ID, flags=DF, offset
+        buf.put((byte) tcpDetails.ttl);             // TTL
+        buf.put((byte) OsConstants.IPPROTO_TCP);
+        final int ipChecksumOffset = buf.position();
+        buf.putShort((short) 0);                    // IP checksum
+        buf.put(tcpDetails.srcAddress);
+        buf.put(tcpDetails.dstAddress);
+        buf.putShort((short) tcpDetails.srcPort);
+        buf.putShort((short) tcpDetails.dstPort);
+        buf.putInt(tcpDetails.seq);                 // Sequence Number
+        buf.putInt(tcpDetails.ack);                 // ACK
+        buf.putShort((short) 0x5010);               // TCP length=5, flags=ACK
+        buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale));   // Window size
+        final int tcpChecksumOffset = buf.position();
+        buf.putShort((short) 0);                    // TCP checksum
+        // URG is not set therefore the urgent pointer is zero.
+        buf.putShort((short) 0);                    // Urgent pointer
+
+        buf.putShort(ipChecksumOffset, com.android.net.module.util.IpUtils.ipChecksum(buf, 0));
+        buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
+                buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
+
+        return buf.array();
+    }
+
+    // TODO: add buildV6Packet.
+
+    /**
+     * Get a {@link TcpKeepalivePacketDataParcelable} from {@link KeepalivePacketData}, if the
+     * generic class actually contains TCP keepalive data.
+     *
+     * @deprecated This method is used on R platforms where android.net.TcpKeepalivePacketData was
+     * not yet system API. Newer platforms should use android.net.TcpKeepalivePacketData directly.
+     *
+     * @param data A {@link KeepalivePacketData} that may contain TCP keepalive data.
+     * @return A parcelable containing TCP keepalive data, or null if the input data does not
+     *         contain TCP keepalive data.
+     */
+    @Deprecated
+    @SuppressWarnings("AndroidFrameworkCompatChange") // API version check used to Log.wtf
+    @Nullable
+    public static TcpKeepalivePacketDataParcelable parseTcpKeepalivePacketData(
+            @Nullable KeepalivePacketData data) {
+        if (data == null) return null;
+
+        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+            Log.wtf(TAG, "parseTcpKeepalivePacketData should not be used after R, use "
+                    + "TcpKeepalivePacketData instead.");
+        }
+
+        // Reconstruct TcpKeepalivePacketData from the packet contained in KeepalivePacketData
+        final ByteBuffer buffer = ByteBuffer.wrap(data.getPacket());
+        buffer.order(ByteOrder.BIG_ENDIAN);
+
+        // Most of the fields are accessible from the KeepalivePacketData superclass: instead of
+        // using Struct to parse everything, just extract the extra fields necessary for
+        // TcpKeepalivePacketData.
+        final int tcpSeq;
+        final int tcpAck;
+        final int wndSize;
+        final int ipTos;
+        final int ttl;
+        try {
+            // This only support IPv4, because TcpKeepalivePacketData only supports IPv4 for R and
+            // below, and this method should not be used on newer platforms.
+            tcpSeq = buffer.getInt(IPV4_HEADER_LENGTH + 4);
+            tcpAck = buffer.getInt(IPV4_HEADER_LENGTH + 8);
+            wndSize = buffer.getShort(IPV4_HEADER_LENGTH + 14);
+            ipTos = buffer.get(1);
+            ttl = buffer.get(8);
+        } catch (IndexOutOfBoundsException e) {
+            return null;
+        }
+
+        final TcpKeepalivePacketDataParcelable p = new TcpKeepalivePacketDataParcelable();
+        p.srcAddress = data.getSrcAddress().getAddress();
+        p.srcPort = data.getSrcPort();
+        p.dstAddress = data.getDstAddress().getAddress();
+        p.dstPort = data.getDstPort();
+        p.seq = tcpSeq;
+        p.ack = tcpAck;
+        // TcpKeepalivePacketData could actually use non-zero wndScale, but this does not affect
+        // actual functionality as generated packets will be the same (no wndScale option added)
+        p.rcvWnd = wndSize;
+        p.rcvWndScale = 0;
+        p.tos = ipTos;
+        p.ttl = ttl;
+        return p;
+    }
 }
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 03083c1..7c935d5 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -19,6 +19,7 @@
 
     static_libs: [
         "services.core",
+        "services.devicepolicy",
         "services.net",
         "services.usage",
         "service-jobscheduler",
diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
new file mode 100644
index 0000000..45160dc
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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 com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RecoverySystem;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+/**
+ * Run it as {@code atest FrameworksMockingCoreTests:FactoryResetterTest}
+ */
+@Presubmit
+public final class FactoryResetterTest {
+
+    private static final String TAG = FactoryResetterTest.class.getSimpleName();
+
+    // Fixed parameters
+    private static final String REASON = "self-destruct";
+    private static final boolean SHUTDOWN = true;
+    private static final boolean WIPE_EUICC = true;
+
+    // Parameters under test
+    private static final boolean FORCE = true;
+    private static final boolean NO_FORCE = false;
+    private static final boolean WIPE_ADOPTABLE_STORAGE = true;
+    private static final boolean NO_WIPE_ADOPTABLE_STORAGE = false;
+    private static final boolean WIPE_FACTORY_RESET_PROTECTION = true;
+    private static final boolean NO_WIPE_FACTORY_RESET_PROTECTION = false;
+
+    private MockitoSession mSession;
+
+    private @Mock Context mContext;
+    private @Mock StorageManager mSm;
+    private @Mock PersistentDataBlockManager mPdbm;
+    private @Mock UserManager mUm;
+
+    @Before
+    public void startSession() {
+        mSession = mockitoSession()
+                .initMocks(this)
+                .spyStatic(RecoverySystem.class)
+                .strictness(Strictness.LENIENT)
+                .startMocking();
+
+        when(mContext.getSystemService(any(String.class))).thenAnswer((inv) -> {
+            Log.d(TAG, "Mocking " + inv);
+            String service = (String) inv.getArguments()[0];
+            switch (service) {
+                case Context.PERSISTENT_DATA_BLOCK_SERVICE:
+                    return mPdbm;
+                case Context.STORAGE_SERVICE:
+                    return mSm;
+                case Context.USER_SERVICE:
+                    return mUm;
+                default:
+                    throw new IllegalArgumentException("Not expecting call for " + service);
+            }
+        });
+
+        doAnswer((inv) -> {
+            Log.d(TAG, "Mocking " + inv);
+            return null;
+        }).when(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(),
+                anyBoolean(), anyBoolean()));
+    }
+
+    @After
+    public void finishSession() {
+        if (mSession == null) {
+            Log.w(TAG, "finishSession(): no session");
+            return;
+        }
+        mSession.finishMocking();
+    }
+
+    @Test
+    public void testFactoryReset_noMasterClearPermission() throws Exception {
+        revokeMasterClearPermission();
+        setFactoryResetRestriction(/* allowed= */ true);
+
+        assertThrows(SecurityException.class,
+                () -> FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+                        WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION));
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataNotCalled();
+    }
+
+    @Test
+    public void testFactoryReset_noForceDisallowed()
+            throws Exception {
+        setFactoryResetRestriction(/* allowed= */ false);
+
+        assertThrows(SecurityException.class,
+                () -> FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+                        WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION));
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataNotCalled();
+    }
+
+    @Test
+    public void testFactoryReset_noForceAllowed() throws Exception {
+        setFactoryResetRestriction(/* allowed= */ true);
+
+        FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+                WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+        verifyWipeAdoptableStorageCalled();
+        verifyWipeFactoryResetProtectionCalled();
+        verifyRebootWipeUserDataCalled(NO_FORCE);
+    }
+
+    @Test
+    public void testFactoryReset_forceDisallowed() throws Exception {
+        setFactoryResetRestriction(/* allowed= */ false);
+
+        FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+                WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+        verifyWipeAdoptableStorageCalled();
+        verifyWipeFactoryResetProtectionCalled();
+        verifyRebootWipeUserDataCalled(FORCE);
+    }
+
+    @Test
+    public void testFactoryReset_bothFalse() throws Exception {
+        FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+                WIPE_EUICC, NO_WIPE_ADOPTABLE_STORAGE, NO_WIPE_FACTORY_RESET_PROTECTION);
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataCalled(FORCE);
+    }
+
+    @Test
+    public void testFactoryReset_storageOnly() throws Exception {
+        FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+                WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, NO_WIPE_FACTORY_RESET_PROTECTION);
+
+        verifyWipeAdoptableStorageCalled();
+        verifyWipeFactoryResetProtectionNotCalled();
+        verifyRebootWipeUserDataCalled(FORCE);
+    }
+
+    @Test
+    public void testFactoryReset_frpOnly() throws Exception {
+        FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+                WIPE_EUICC, NO_WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+        verifyWipeAdoptableStorageNotCalled();
+        verifyWipeFactoryResetProtectionCalled();
+        verifyRebootWipeUserDataCalled(FORCE);
+    }
+
+    private void revokeMasterClearPermission() {
+        when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.MASTER_CLEAR))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+    }
+
+    private void setFactoryResetRestriction(boolean allowed) {
+        when(mUm.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)).thenReturn(!allowed);
+    }
+
+    private void verifyRebootWipeUserDataNotCalled() {
+        verify(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(),
+                anyBoolean()), never());
+    }
+
+    private void verifyRebootWipeUserDataCalled(boolean force) {
+        verify(() -> RecoverySystem.rebootWipeUserData(mContext, SHUTDOWN, REASON, force,
+                WIPE_EUICC));
+    }
+
+    private void verifyWipeAdoptableStorageNotCalled() {
+        verify(mSm, never()).wipeAdoptableDisks();
+    }
+
+    private void verifyWipeAdoptableStorageCalled() {
+        verify(mSm).wipeAdoptableDisks();
+    }
+
+    private void verifyWipeFactoryResetProtectionNotCalled() {
+        verify(mPdbm, never()).wipe();
+    }
+
+    private void verifyWipeFactoryResetProtectionCalled() {
+        verify(mPdbm).wipe();
+    }
+}
diff --git a/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log
new file mode 100644
index 0000000..cf791f2
--- /dev/null
+++ b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log
@@ -0,0 +1,29 @@
+ * Gesture6_id30:Swipe down with 3 finger
+MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_DOWN(1), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_DOWN(2), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=766.0, y[1]=811.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273715, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=503.0, y[0]=699.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=773.0, y[1]=838.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273725, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=521.0, y[0]=728.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=776.0, y[1]=862.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=305.0, y[2]=876.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273734, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=535.0, y[0]=765.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=782.0, y[1]=898.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=313.0, y[2]=911.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273741, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=545.0, y[0]=795.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=786.0, y[1]=918.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=323.0, y[2]=941.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273750, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=555.0, y[0]=832.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=790.0, y[1]=959.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=333.0, y[2]=976.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273758, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=560.0, y[0]=870.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=794.0, y[1]=988.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=339.0, y[2]=1020.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273767, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=565.0, y[0]=909.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=797.0, y[1]=1031.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=345.0, y[2]=1052.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273776, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=568.0, y[0]=948.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=801.0, y[1]=1060.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=348.0, y[2]=1102.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273784, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=570.0, y[0]=985.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=804.0, y[1]=1103.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=352.0, y[2]=1130.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273793, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=571.0, y[0]=1028.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=807.0, y[1]=1133.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=355.0, y[2]=1178.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273801, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=572.0, y[0]=1061.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=809.0, y[1]=1175.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=358.0, y[2]=1212.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273810, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=574.0, y[0]=1108.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=811.0, y[1]=1206.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=360.0, y[2]=1260.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273822, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=575.0, y[0]=1141.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=812.0, y[1]=1249.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=363.0, y[2]=1294.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273831, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=576.0, y[0]=1191.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=815.0, y[1]=1281.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=364.0, y[2]=1343.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273836, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=578.0, y[0]=1227.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=816.0, y[1]=1324.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=368.0, y[2]=1374.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273844, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1276.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=820.0, y[1]=1360.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=371.0, y[2]=1421.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273853, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1324.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=823.0, y[1]=1406.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=372.0, y[2]=1464.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273862, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=584.0, y[0]=1369.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=824.0, y[1]=1445.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=379.0, y[2]=1506.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273870, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273879, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273888, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=1, x[0]=826.0, y[0]=1493.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=2, x[1]=387.0, y[1]=1553.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_UP, actionButton=0, id[0]=2, x[0]=387.0, y[0]=1553.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log
new file mode 100644
index 0000000..3cfb0a7
--- /dev/null
+++ b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log
@@ -0,0 +1,4 @@
+* Gesture4_id-2:Touch explore
+MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258108, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258133, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258141, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 89bd625..7bf0bb8 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -35,7 +35,10 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
 
+import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityService;
 import android.content.Context;
 import android.graphics.PointF;
 import android.os.Looper;
@@ -51,6 +54,7 @@
 
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accessibility.EventStreamTransformation;
+import com.android.server.accessibility.utils.GestureLogParser;
 import com.android.server.testutils.OffsettableClock;
 
 import org.junit.Before;
@@ -58,7 +62,15 @@
 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.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -93,6 +105,11 @@
     private int mTouchSlop;
     private long mLastDownTime = Integer.MIN_VALUE;
 
+    @Mock
+    private AccessibilityManagerService mMockAms;
+    @Captor
+    private ArgumentCaptor<AccessibilityGestureEvent> mGestureCaptor;
+
     // mock package-private GestureManifold class
     @Rule
     public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -122,6 +139,7 @@
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
@@ -130,7 +148,7 @@
         AccessibilityManagerService ams = new AccessibilityManagerService(mContext);
         mCaptor = new EventCaptor();
         mHandler = new TestHandler();
-        mTouchExplorer = new TouchExplorer(mContext, ams, null, mHandler);
+        mTouchExplorer = new TouchExplorer(mContext, mMockAms, null, mHandler);
         mTouchExplorer.setNext(mCaptor);
     }
 
@@ -395,6 +413,61 @@
         mTouchExplorer.setMultiFingerGesturesEnabled(false);
     }
 
+    @Test
+    public void testTouchExploreGestureLog() {
+        passInGesture(com.android.frameworks.servicestests.R.raw.a11y_touch_explore_gesture,
+                AccessibilityService.GESTURE_TOUCH_EXPLORATION);
+    }
+    @Test
+    public void testThreeFingerSwipeDownGestureLog() {
+        passInGesture(
+                com.android.frameworks.servicestests.R.raw.a11y_three_finger_swipe_down_gesture,
+                AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN);
+    }
+
+    /**
+     * Used to play back event data of a gesture by parsing the log into MotionEvents and sending
+     * them to TouchExplorer.
+     * @param resourceId a raw resource that corresponds to a text file
+     * @param gestureId the id of the gesture expected to be dispatched
+     */
+    private void passInGesture(int resourceId, int gestureId) {
+        mTouchExplorer.setMultiFingerGesturesEnabled(true);
+        mTouchExplorer.setSendMotionEventsEnabled(true);
+        mTouchExplorer.setTwoFingerPassthroughEnabled(true);
+        List<Integer> actions = new ArrayList<>();
+        try (
+            InputStream fis = mContext.getResources().openRawResource(resourceId);
+            InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
+            BufferedReader br = new BufferedReader(isr);
+        )  {
+            String line;
+            while ((line = br.readLine()) != null) {
+                if (line.isEmpty() || !line.contains("MotionEvent")) {
+                    continue;
+                }
+
+                MotionEvent motionEvent = GestureLogParser.getMotionEventFromLogLine(line);
+                actions.add(motionEvent.getAction());
+                send(motionEvent);
+            }
+
+            // Fast forward to dispatch GESTURE_TOUCH_EXPLORATION
+            mHandler.fastForward(USER_INTENT_TIMEOUT);
+        } catch (IOException ioException) {
+            ioException.printStackTrace();
+        }
+
+        verify(mMockAms).onGesture(mGestureCaptor.capture());
+        AccessibilityGestureEvent gestureEvent = mGestureCaptor.getValue();
+        assertEquals(gestureId, gestureEvent.getGestureId());
+        List<MotionEvent> motionEvents = gestureEvent.getMotionEvents();
+        assertEquals(actions.size(), motionEvents.size());
+        for (int i = 0; i < actions.size(); i++) {
+            assertEquals((int) actions.get(i), motionEvents.get(i).getAction());
+        }
+    }
+
     private static MotionEvent fromTouchscreen(MotionEvent ev) {
         ev.setSource(InputDevice.SOURCE_TOUCHSCREEN);
         return ev;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java
new file mode 100644
index 0000000..cd848f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java
@@ -0,0 +1,169 @@
+/*
+ * 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.accessibility.utils;
+
+import android.view.MotionEvent;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class helps parse a gesture event log into its individual MotionEvents
+ */
+public class GestureLogParser {
+    /** Gets a MotionEvent from a log line */
+    public static MotionEvent getMotionEventFromLogLine(String line) {
+        final int downTime;
+        final int eventTime;
+        int action;
+        final int pointerCount;
+
+        final MotionEvent.PointerProperties[] properties;
+        final MotionEvent.PointerCoords[] pointerCoords;
+        final int metaState;
+        final int buttonState = 0;
+        final int xPrecision = 1;
+        final int yPrecision = 1;
+        final int deviceId;
+        final int edgeFlags;
+        final int source;
+        final int flags;
+        final int actionIndex;
+
+        downTime = findInt(line, "downTime=(\\d+)");
+        eventTime = findInt(line, "eventTime=(\\d+)");
+        action = stringToAction(findString(line, "action=(\\w+)"));
+
+        // For pointer indices
+        Pattern p = Pattern.compile("action=(\\w+)\\((\\d)");
+        Matcher matcher = p.matcher(line);
+        if (matcher.find()) {
+            actionIndex = Integer.decode(matcher.group(2));
+            action = action | (actionIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+        }
+
+        pointerCount = findInt(line, "pointerCount=(\\d+)");
+        metaState = findInt(line, "metaState=(\\d+)");
+        deviceId = findInt(line, "deviceId=(\\d+)");
+        edgeFlags = Integer.decode(findString(line, "edgeFlags=(\\w+)"));
+        source = Integer.decode(findString(line, "source=(\\w+)"));
+        flags = Integer.decode(findString(line, "flags=(\\w+)"));
+        properties = findProperties(line, pointerCount);
+        pointerCoords = findCoordinates(line, pointerCount);
+
+        return MotionEvent.obtain(downTime, eventTime, action,
+                pointerCount, properties, pointerCoords, metaState, buttonState,
+                xPrecision, yPrecision, deviceId, edgeFlags, source, flags);
+    }
+
+    private static int findInt(String eventText, String pattern) {
+        final Pattern p = Pattern.compile(pattern);
+        final Matcher matcher = p.matcher(eventText);
+        matcher.find();
+        return Integer.decode(matcher.group(1));
+    }
+
+    private static float findFloat(String eventText, String pattern) {
+        final Pattern p = Pattern.compile(pattern);
+        final Matcher matcher = p.matcher(eventText);
+        matcher.find();
+        return Float.parseFloat(matcher.group(1));
+    }
+
+    private static String findString(String eventText, String pattern) {
+        final Pattern p = Pattern.compile(pattern);
+        final Matcher matcher = p.matcher(eventText);
+        matcher.find();
+        return matcher.group(1);
+    }
+
+    private static MotionEvent.PointerCoords[] findCoordinates(String eventText, int pointerCount) {
+        if (pointerCount == 0) {
+            return null;
+        }
+
+        final MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointerCount];
+        float x;
+        float y;
+        for (int i = 0; i < pointerCount; i++) {
+
+            x = findFloat(eventText, "x\\[" + i + "\\]=([\\d.]+)");
+            y = findFloat(eventText, "y\\[" + i + "\\]=([\\d.]+)");
+
+            MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
+            pointerCoords.x = x;
+            pointerCoords.y = y;
+            pointerCoords.pressure = 1;
+            pointerCoords.size = 1;
+
+            coords[i] = pointerCoords;
+        }
+        return coords;
+    }
+
+    private static MotionEvent.PointerProperties[] findProperties(
+            String eventText, int pointerCount) {
+        if (pointerCount == 0) {
+            return null;
+        }
+
+        final MotionEvent.PointerProperties[] props =
+                new MotionEvent.PointerProperties[pointerCount];
+        int id;
+        for (int i = 0; i < pointerCount; i++) {
+            id = findInt(eventText, "id\\[" + i + "\\]=([\\d])");
+            MotionEvent.PointerProperties pointerProps = new MotionEvent.PointerProperties();
+            pointerProps.id = id;
+            pointerProps.toolType = MotionEvent.TOOL_TYPE_FINGER;
+            props[i] = pointerProps;
+        }
+        return props;
+    }
+
+    private static int stringToAction(String action) {
+        switch (action) {
+            case "ACTION_DOWN":
+                return MotionEvent.ACTION_DOWN;
+            case "ACTION_UP":
+                return MotionEvent.ACTION_UP;
+            case "ACTION_CANCEL":
+                return MotionEvent.ACTION_CANCEL;
+            case "ACTION_OUTSIDE":
+                return MotionEvent.ACTION_OUTSIDE;
+            case "ACTION_MOVE":
+                return MotionEvent.ACTION_MOVE;
+            case "ACTION_HOVER_MOVE":
+                return MotionEvent.ACTION_HOVER_MOVE;
+            case "ACTION_SCROLL":
+                return MotionEvent.ACTION_SCROLL;
+            case "ACTION_HOVER_ENTER":
+                return MotionEvent.ACTION_HOVER_ENTER;
+            case "ACTION_HOVER_EXIT":
+                return MotionEvent.ACTION_HOVER_EXIT;
+            case "ACTION_BUTTON_PRESS":
+                return MotionEvent.ACTION_BUTTON_PRESS;
+            case "ACTION_BUTTON_RELEASE":
+                return MotionEvent.ACTION_BUTTON_RELEASE;
+            case "ACTION_POINTER_DOWN":
+                return MotionEvent.ACTION_POINTER_DOWN;
+            case "ACTION_POINTER_UP":
+                return MotionEvent.ACTION_POINTER_UP;
+            default:
+                return -1;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index f38def8..f36ed4b 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -58,22 +58,21 @@
     public void setUp() throws Exception {
         mAppSearchImpl = AppSearchImpl.create(mTemporaryFolder.newFolder());
 
-        AppSearchSchema visibilityAppSearchSchema =
+        AppSearchSchema visibilitySchema = VisibilityStore.SCHEMA;
+
+        // We need to rewrite the schema type to follow AppSearchImpl's prefixing scheme.
+        AppSearchSchema.Builder rewrittenVisibilitySchema =
                 new AppSearchSchema.Builder(
-                                VisibilityStore.DATABASE_NAME
-                                        + AppSearchImpl.DATABASE_DELIMITER
-                                        + VisibilityStore.SCHEMA_TYPE)
-                        .addProperty(
-                                new AppSearchSchema.PropertyConfig.Builder(
-                                                VisibilityStore.NOT_PLATFORM_SURFACEABLE_PROPERTY)
-                                        .setDataType(
-                                                AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
-                                        .setCardinality(
-                                                AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
-                                        .build())
-                        .build();
+                        AppSearchImpl.createPrefix(
+                                        VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME)
+                                + VisibilityStore.SCHEMA_TYPE);
+        List<AppSearchSchema.PropertyConfig> visibilityProperties =
+                visibilitySchema.getProperties();
+        for (AppSearchSchema.PropertyConfig property : visibilityProperties) {
+            rewrittenVisibilitySchema.addProperty(property);
+        }
         mVisibilitySchemaProto =
-                SchemaToProtoConverter.toSchemaTypeConfigProto(visibilityAppSearchSchema);
+                SchemaToProtoConverter.toSchemaTypeConfigProto(rewrittenVisibilitySchema.build());
     }
 
     /**
@@ -87,7 +86,7 @@
                 SchemaProto.newBuilder()
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("existingDatabase/Foo")
+                                        .setSchemaType("package$existingDatabase/Foo")
                                         .build());
 
         // Create a copy so we can modify it.
@@ -135,22 +134,25 @@
                         .build();
 
         AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
-                mAppSearchImpl.rewriteSchema("newDatabase", existingSchemaBuilder, newSchema);
+                mAppSearchImpl.rewriteSchema(
+                        AppSearchImpl.createPrefix("package", "newDatabase"),
+                        existingSchemaBuilder,
+                        newSchema);
 
         // We rewrote all the new types that were added. And nothing was removed.
-        assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
-                .containsExactly("newDatabase/Foo", "newDatabase/TestType");
-        assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+        assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+                .containsExactly("package$newDatabase/Foo", "package$newDatabase/TestType");
+        assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
 
         SchemaProto expectedSchema =
                 SchemaProto.newBuilder()
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("newDatabase/Foo")
+                                        .setSchemaType("package$newDatabase/Foo")
                                         .build())
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("newDatabase/TestType")
+                                        .setSchemaType("package$newDatabase/TestType")
                                         .addProperties(
                                                 PropertyConfigProto.newBuilder()
                                                         .setPropertyName("subject")
@@ -180,7 +182,8 @@
                                                         .setCardinality(
                                                                 PropertyConfigProto.Cardinality.Code
                                                                         .OPTIONAL)
-                                                        .setSchemaType("newDatabase/RefType")
+                                                        .setSchemaType(
+                                                                "package$newDatabase/RefType")
                                                         .build())
                                         .build())
                         .build();
@@ -199,7 +202,7 @@
                 SchemaProto.newBuilder()
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("existingDatabase/Foo")
+                                        .setSchemaType("package$existingDatabase/Foo")
                                         .build());
 
         SchemaProto newSchema =
@@ -208,12 +211,15 @@
                         .build();
 
         AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
-                mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+                mAppSearchImpl.rewriteSchema(
+                        AppSearchImpl.createPrefix("package", "existingDatabase"),
+                        existingSchemaBuilder,
+                        newSchema);
 
         // Nothing was removed, but the method did rewrite the type name.
-        assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
-                .containsExactly("existingDatabase/Foo");
-        assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+        assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+                .containsExactly("package$existingDatabase/Foo");
+        assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
 
         // Same schema since nothing was added.
         SchemaProto expectedSchema = existingSchemaBuilder.build();
@@ -231,7 +237,7 @@
                 SchemaProto.newBuilder()
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("existingDatabase/Foo")
+                                        .setSchemaType("package$existingDatabase/Foo")
                                         .build());
 
         SchemaProto newSchema =
@@ -240,21 +246,24 @@
                         .build();
 
         AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
-                mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+                mAppSearchImpl.rewriteSchema(
+                        AppSearchImpl.createPrefix("package", "existingDatabase"),
+                        existingSchemaBuilder,
+                        newSchema);
 
         // Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the
         // new schema.
-        assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
-                .containsExactly("existingDatabase/Bar");
-        assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes)
-                .containsExactly("existingDatabase/Foo");
+        assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+                .containsExactly("package$existingDatabase/Bar");
+        assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes)
+                .containsExactly("package$existingDatabase/Foo");
 
         // Same schema since nothing was added.
         SchemaProto expectedSchema =
                 SchemaProto.newBuilder()
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("existingDatabase/Bar")
+                                        .setSchemaType("package$existingDatabase/Bar")
                                         .build())
                         .build();
 
@@ -281,21 +290,22 @@
         DocumentProto expectedInsideDocument =
                 DocumentProto.newBuilder()
                         .setUri("inside-uri")
-                        .setSchema("databaseName/type")
-                        .setNamespace("databaseName/namespace")
+                        .setSchema("package$databaseName/type")
+                        .setNamespace("package$databaseName/namespace")
                         .build();
         DocumentProto expectedDocumentProto =
                 DocumentProto.newBuilder()
                         .setUri("uri")
-                        .setSchema("databaseName/type")
-                        .setNamespace("databaseName/namespace")
+                        .setSchema("package$databaseName/type")
+                        .setNamespace("package$databaseName/namespace")
                         .addProperties(
                                 PropertyProto.newBuilder()
                                         .addDocumentValues(expectedInsideDocument))
                         .build();
 
         DocumentProto.Builder actualDocument = documentProto.toBuilder();
-        mAppSearchImpl.addPrefixToDocument(actualDocument, "databaseName/");
+        mAppSearchImpl.addPrefixToDocument(
+                actualDocument, AppSearchImpl.createPrefix("package", "databaseName"));
         assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
     }
 
@@ -304,14 +314,14 @@
         DocumentProto insideDocument =
                 DocumentProto.newBuilder()
                         .setUri("inside-uri")
-                        .setSchema("databaseName1/type")
-                        .setNamespace("databaseName2/namespace")
+                        .setSchema("package$databaseName1/type")
+                        .setNamespace("package$databaseName2/namespace")
                         .build();
         DocumentProto documentProto =
                 DocumentProto.newBuilder()
                         .setUri("uri")
-                        .setSchema("databaseName2/type")
-                        .setNamespace("databaseName3/namespace")
+                        .setSchema("package$databaseName2/type")
+                        .setNamespace("package$databaseName3/namespace")
                         .addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
                         .build();
 
@@ -321,7 +331,7 @@
                         .setSchema("type")
                         .setNamespace("namespace")
                         .build();
-        // Since we don't pass in "databaseName3/" as a prefix to remove, it stays on the Document.
+
         DocumentProto expectedDocumentProto =
                 DocumentProto.newBuilder()
                         .setUri("uri")
@@ -333,7 +343,7 @@
                         .build();
 
         DocumentProto.Builder actualDocument = documentProto.toBuilder();
-        mAppSearchImpl.removeDatabasesFromDocument(actualDocument);
+        mAppSearchImpl.removePrefixesFromDocument(actualDocument);
         assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
     }
 
@@ -343,6 +353,7 @@
         List<AppSearchSchema> schemas =
                 Collections.singletonList(new AppSearchSchema.Builder("type").build());
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -358,7 +369,7 @@
                     new GenericDocument.Builder<>("uri" + i, "type")
                             .setNamespace("namespace")
                             .build();
-            mAppSearchImpl.putDocument("database", document);
+            mAppSearchImpl.putDocument("package", "database", document);
         }
 
         // Check optimize() will release 0 docs since there is no deletion.
@@ -368,7 +379,7 @@
         // delete 999 documents , we will reach the threshold to trigger optimize() in next
         // deletion.
         for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1; i++) {
-            mAppSearchImpl.remove("database", "namespace", "uri" + i);
+            mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
         }
 
         // optimize() still not be triggered since we are in the interval to call getOptimizeInfo()
@@ -382,7 +393,7 @@
                         < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
                                 + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
                 i++) {
-            mAppSearchImpl.remove("database", "namespace", "uri" + i);
+            mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
         }
 
         // Verify optimize() is triggered
@@ -399,6 +410,7 @@
         List<AppSearchSchema> schemas =
                 Collections.singletonList(new AppSearchSchema.Builder("type").build());
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -407,13 +419,16 @@
         // Insert document
         GenericDocument document =
                 new GenericDocument.Builder<>("uri", "type").setNamespace("namespace").build();
-        mAppSearchImpl.putDocument("database", document);
+        mAppSearchImpl.putDocument("package", "database", document);
 
         // Rewrite SearchSpec
-        mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
-                searchSpecProto, Collections.singleton("database"));
-        assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly("database/type");
-        assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly("database/namespace");
+        mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
+                searchSpecProto,
+                Collections.singleton(AppSearchImpl.createPrefix("package", "database")));
+        assertThat(searchSpecProto.getSchemaTypeFiltersList())
+                .containsExactly("package$database/type");
+        assertThat(searchSpecProto.getNamespaceFiltersList())
+                .containsExactly("package$database/namespace");
     }
 
     @Test
@@ -426,11 +441,13 @@
                         new AppSearchSchema.Builder("typeA").build(),
                         new AppSearchSchema.Builder("typeB").build());
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
         mAppSearchImpl.setSchema(
+                "package",
                 "database2",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -439,27 +456,34 @@
         // Insert documents
         GenericDocument document1 =
                 new GenericDocument.Builder<>("uri", "typeA").setNamespace("namespace").build();
-        mAppSearchImpl.putDocument("database1", document1);
+        mAppSearchImpl.putDocument("package", "database1", document1);
 
         GenericDocument document2 =
                 new GenericDocument.Builder<>("uri", "typeB").setNamespace("namespace").build();
-        mAppSearchImpl.putDocument("database2", document2);
+        mAppSearchImpl.putDocument("package", "database2", document2);
 
         // Rewrite SearchSpec
-        mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
-                searchSpecProto, ImmutableSet.of("database1", "database2"));
+        mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
+                searchSpecProto,
+                ImmutableSet.of(
+                        AppSearchImpl.createPrefix("package", "database1"),
+                        AppSearchImpl.createPrefix("package", "database2")));
         assertThat(searchSpecProto.getSchemaTypeFiltersList())
                 .containsExactly(
-                        "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB");
+                        "package$database1/typeA",
+                        "package$database1/typeB",
+                        "package$database2/typeA",
+                        "package$database2/typeB");
         assertThat(searchSpecProto.getNamespaceFiltersList())
-                .containsExactly("database1/namespace", "database2/namespace");
+                .containsExactly("package$database1/namespace", "package$database2/namespace");
     }
 
     @Test
     public void testQueryEmptyDatabase() throws Exception {
         SearchSpec searchSpec =
                 new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
-        SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
+        SearchResultPage searchResultPage =
+                mAppSearchImpl.query("package", "EmptyDatabase", "", searchSpec);
         assertThat(searchResultPage.getResults()).isEmpty();
     }
 
@@ -467,7 +491,7 @@
     public void testGlobalQueryEmptyDatabase() throws Exception {
         SearchSpec searchSpec =
                 new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
-        SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
+        SearchResultPage searchResultPage = mAppSearchImpl.globalQuery("", searchSpec);
         assertThat(searchResultPage.getResults()).isEmpty();
     }
 
@@ -478,17 +502,17 @@
                         .addSchemaType("FakeType")
                         .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
                         .build();
-        mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+        mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
 
         searchSpec =
                 new SearchSpec.Builder()
                         .addNamespace("FakeNamespace")
                         .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
                         .build();
-        mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+        mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
 
         searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
-        mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+        mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
     }
 
     @Test
@@ -497,6 +521,7 @@
                 Collections.singletonList(new AppSearchSchema.Builder("Email").build());
         // Set schema Email to AppSearch database1
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -506,7 +531,8 @@
         SchemaProto expectedProto =
                 SchemaProto.newBuilder()
                         .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database1/Email"))
                         .build();
 
         List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
@@ -518,7 +544,9 @@
 
     @Test
     public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
+        String prefix = AppSearchImpl.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
@@ -528,11 +556,12 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("database/schema1");
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+                .isFalse();
 
         // Add a new schema, and include the already-existing "schema1"
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 ImmutableList.of(
                         new AppSearchSchema.Builder("schema1").build(),
@@ -545,8 +574,13 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("database/schema1");
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+                .isFalse();
+        assertThat(
+                        mAppSearchImpl
+                                .getVisibilityStoreLocked()
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema2"))
+                .isTrue();
     }
 
     @Test
@@ -557,6 +591,7 @@
                         new AppSearchSchema.Builder("Document").build());
         // Set schema Email and Document to AppSearch database1
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -566,10 +601,11 @@
         SchemaProto expectedProto =
                 SchemaProto.newBuilder()
                         .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database1/Email"))
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("database1/Document"))
+                                        .setSchemaType("package$database1/Document"))
                         .build();
 
         // Check both schema Email and Document saved correctly.
@@ -587,15 +623,17 @@
                         AppSearchException.class,
                         () ->
                                 mAppSearchImpl.setSchema(
+                                        "package",
                                         "database1",
                                         finalSchemas,
                                         /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                                         /*forceOverride=*/ false));
         assertThat(e).hasMessageThat().contains("Schema is incompatible");
-        assertThat(e).hasMessageThat().contains("Deleted types: [database1/Document]");
+        assertThat(e).hasMessageThat().contains("Deleted types: [package$database1/Document]");
 
         // ForceOverride to delete.
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 finalSchemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -605,7 +643,8 @@
         expectedProto =
                 SchemaProto.newBuilder()
                         .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database1/Email"))
                         .build();
 
         expectedTypes = new ArrayList<>();
@@ -625,11 +664,13 @@
 
         // Set schema Email and Document to AppSearch database1 and 2
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
         mAppSearchImpl.setSchema(
+                "package",
                 "database2",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -639,15 +680,17 @@
         SchemaProto expectedProto =
                 SchemaProto.newBuilder()
                         .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database1/Email"))
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("database1/Document"))
-                        .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+                                        .setSchemaType("package$database1/Document"))
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("database2/Document"))
+                                        .setSchemaType("package$database2/Email"))
+                        .addTypes(
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database2/Document"))
                         .build();
 
         // Check Email and Document is saved in database 1 and 2 correctly.
@@ -660,6 +703,7 @@
         // Save only Email to database1 this time.
         schemas = Collections.singletonList(new AppSearchSchema.Builder("Email").build());
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 schemas,
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -670,12 +714,14 @@
         expectedProto =
                 SchemaProto.newBuilder()
                         .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
-                        .addTypes(
-                                SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database1/Email"))
                         .addTypes(
                                 SchemaTypeConfigProto.newBuilder()
-                                        .setSchemaType("database2/Document"))
+                                        .setSchemaType("package$database2/Email"))
+                        .addTypes(
+                                SchemaTypeConfigProto.newBuilder()
+                                        .setSchemaType("package$database2/Document"))
                         .build();
 
         // Check nothing changed in database2.
@@ -688,7 +734,9 @@
 
     @Test
     public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
+        String prefix = AppSearchImpl.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
@@ -698,11 +746,12 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("database/schema1");
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+                .isFalse();
 
         // Remove "schema1" by force overriding
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.emptyList(),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -712,12 +761,13 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .isEmpty();
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+                .isTrue();
 
         // Add "schema1" back, it gets default visibility settings which means it's not platform
         // hidden.
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -725,13 +775,15 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .isEmpty();
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+                .isTrue();
     }
 
     @Test
     public void testSetSchema_defaultPlatformVisible() throws Exception {
+        String prefix = AppSearchImpl.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -739,13 +791,15 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .isEmpty();
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "Schema"))
+                .isTrue();
     }
 
     @Test
     public void testSetSchema_platformHidden() throws Exception {
+        String prefix = AppSearchImpl.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
@@ -753,47 +807,60 @@
         assertThat(
                         mAppSearchImpl
                                 .getVisibilityStoreLocked()
-                                .getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("database/Schema");
+                                .isSchemaPlatformSurfaceable(prefix, prefix + "Schema"))
+                .isFalse();
     }
 
     @Test
     public void testHasSchemaType() throws Exception {
         // Nothing exists yet
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isFalse();
+        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse();
 
         mAppSearchImpl.setSchema(
+                "package",
                 "database",
                 Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isTrue();
+        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue();
 
-        assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "UnknownSchema")).isFalse();
+        assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema"))
+                .isFalse();
     }
 
     @Test
     public void testGetDatabases() throws Exception {
         // No client databases exist yet, but the VisibilityStore's does
-        assertThat(mAppSearchImpl.getDatabasesLocked())
-                .containsExactly(VisibilityStore.DATABASE_NAME);
+        assertThat(mAppSearchImpl.getPrefixesLocked())
+                .containsExactly(
+                        AppSearchImpl.createPrefix(
+                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
 
         // Has database1
         mAppSearchImpl.setSchema(
+                "package",
                 "database1",
                 Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.getDatabasesLocked())
-                .containsExactly(VisibilityStore.DATABASE_NAME, "database1");
+        assertThat(mAppSearchImpl.getPrefixesLocked())
+                .containsExactly(
+                        AppSearchImpl.createPrefix(
+                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
+                        AppSearchImpl.createPrefix("package", "database1"));
 
         // Has both databases
         mAppSearchImpl.setSchema(
+                "package",
                 "database2",
                 Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
                 /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                 /*forceOverride=*/ false);
-        assertThat(mAppSearchImpl.getDatabasesLocked())
-                .containsExactly(VisibilityStore.DATABASE_NAME, "database1", "database2");
+        assertThat(mAppSearchImpl.getPrefixesLocked())
+                .containsExactly(
+                        AppSearchImpl.createPrefix(
+                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
+                        AppSearchImpl.createPrefix("package", "database1"),
+                        AppSearchImpl.createPrefix("package", "database2"));
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
index a1f575a..415c1f5 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
@@ -18,13 +18,14 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import com.google.common.collect.ImmutableSet;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 
 import java.util.Collections;
-import java.util.Set;
 
 public class VisibilityStoreTest {
 
@@ -38,22 +39,78 @@
         mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
     }
 
+    /**
+     * Make sure that we don't conflict with any special characters that AppSearchImpl has reserved.
+     */
+    @Test
+    public void testValidPackageName() {
+        assertThat(VisibilityStore.PACKAGE_NAME)
+                .doesNotContain(
+                        "" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
+        assertThat(VisibilityStore.PACKAGE_NAME)
+                .doesNotContain(
+                        ""
+                                + AppSearchImpl
+                                        .DATABASE_DELIMITER); // Convert the chars to CharSequences
+    }
+
+    /**
+     * Make sure that we don't conflict with any special characters that AppSearchImpl has reserved.
+     */
+    @Test
+    public void testValidDatabaseName() {
+        assertThat(VisibilityStore.DATABASE_NAME)
+                .doesNotContain(
+                        "" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
+        assertThat(VisibilityStore.DATABASE_NAME)
+                .doesNotContain(
+                        ""
+                                + AppSearchImpl
+                                        .DATABASE_DELIMITER); // Convert the chars to CharSequences
+    }
+
     @Test
     public void testSetVisibility() throws Exception {
         mVisibilityStore.setVisibility(
-                "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema2"));
-        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("schema1", "schema2");
+                "prefix",
+                /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+                        "prefix/schema1", "prefix/schema2"));
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+                .isFalse();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+                .isFalse();
 
         // New .setVisibility() call completely overrides previous visibility settings. So
-        // "schema1" isn't preserved.
+        // "schema2" isn't preserved.
         mVisibilityStore.setVisibility(
-                "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema3"));
-        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
-                .containsExactly("schema1", "schema3");
+                "prefix",
+                /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+                        "prefix/schema1", "prefix/schema3"));
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+                .isFalse();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+                .isTrue();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema3"))
+                .isFalse();
 
         mVisibilityStore.setVisibility(
-                "database", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
-        assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database")).isEmpty();
+                "prefix", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+                .isTrue();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+                .isTrue();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema3"))
+                .isTrue();
+    }
+
+    @Test
+    public void testEmptyPrefix() throws Exception {
+        mVisibilityStore.setVisibility(
+                /*prefix=*/ "",
+                /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of("schema1", "schema2"));
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema1"))
+                .isFalse();
+        assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema2"))
+                .isFalse();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index e2b48d4..17324ba 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -320,8 +320,10 @@
 
         @Override
         void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
-                boolean wipeEuicc) throws IOException {
-            services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc);
+                boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+                        throws IOException {
+            services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc,
+                    wipeExtRequested, wipeResetProtectionData);
         }
 
         @Override
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 d9daf17..1c7da3b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4681,9 +4681,8 @@
                 thenReturn("Just a test string.");
 
         dpm.wipeData(0);
-        verify(getServices().recoverySystem).rebootWipeUserData(
-                /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
-                /*wipeEuicc=*/ eq(false));
+
+        verifyRebootWipeUserData(/* wipeEuicc= */ false);
     }
 
     @Test
@@ -4697,9 +4696,8 @@
                 thenReturn("Just a test string.");
 
         dpm.wipeData(WIPE_EUICC);
-        verify(getServices().recoverySystem).rebootWipeUserData(
-                /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
-                /*wipeEuicc=*/ eq(true));
+
+        verifyRebootWipeUserData(/* wipeEuicc= */ true);
     }
 
     @Test
@@ -4802,9 +4800,7 @@
 
         // The device should be wiped even if DISALLOW_FACTORY_RESET is enabled, because both the
         // user restriction and the policy were set by the DO.
-        verify(getServices().recoverySystem).rebootWipeUserData(
-                /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
-                /*wipeEuicc=*/ eq(false));
+        verifyRebootWipeUserData(/* wipeEuicc= */ false);
     }
 
     @Test
@@ -4863,9 +4859,7 @@
         dpm.reportFailedPasswordAttempt(UserHandle.USER_SYSTEM);
 
         // For managed profile on an organization owned device, the whole device should be wiped.
-        verify(getServices().recoverySystem).rebootWipeUserData(
-                /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
-                /*wipeEuicc=*/ eq(false));
+        verifyRebootWipeUserData(/* wipeEuicc= */ false);
     }
 
     @Test
@@ -4907,9 +4901,7 @@
         dpm.reportFailedPasswordAttempt(MANAGED_PROFILE_USER_ID);
 
         // For managed profile on an organization owned device, the whole device should be wiped.
-        verify(getServices().recoverySystem).rebootWipeUserData(
-                /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
-                /*wipeEuicc=*/ eq(false));
+        verifyRebootWipeUserData(/* wipeEuicc= */ false);
     }
 
     @Test
@@ -5788,6 +5780,12 @@
         });
     }
 
+    private void verifyRebootWipeUserData(boolean wipeEuicc) throws Exception {
+        verify(getServices().recoverySystem).rebootWipeUserData(/*shutdown=*/ eq(false),
+                /* reason= */ anyString(), /*force=*/ eq(true), eq(wipeEuicc),
+                /* wipeAdoptableStorage= */ eq(false), /* wipeFactoryResetProtection= */ eq(false));
+    }
+
     private void assertAttestationFlags(int attestationFlags, int[] expectedFlags) {
         int[] gotFlags = DevicePolicyManagerService.translateIdAttestationFlags(attestationFlags);
         Arrays.sort(gotFlags);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 34313b8..7d1de86 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -393,7 +393,8 @@
 
     public static class RecoverySystemForMock {
         public void rebootWipeUserData(boolean shutdown, String reason, boolean force,
-                boolean wipeEuicc) throws IOException {
+                boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+                        throws IOException {
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 0a3d545..42f88dc 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -79,7 +79,7 @@
     }
 
     private HdmiCecController mHdmiCecController;
-    private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+    private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
     private int mLogicalAddress = 16;
     private AllocateAddressCallback mCallback =
             new AllocateAddressCallback() {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index ef77f32..ae59609 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -284,7 +284,7 @@
     public void handleCecVersion_isHandled() {
         boolean result = mHdmiLocalDevice.onMessage(
                 HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress,
-                        HdmiControlManager.HDMI_CEC_VERSION_1_4_b));
+                        HdmiControlManager.HDMI_CEC_VERSION_1_4_B));
 
         assertThat(result).isTrue();
     }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
index 6496264..453303e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
@@ -104,7 +104,7 @@
     @Test
     public void buildReportFeatures_basicTv_1_4() {
         HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
                 Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
 
@@ -114,7 +114,7 @@
     @Test
     public void buildReportFeatures_basicPlayback_1_4() {
         HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_TV,
                 Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
 
@@ -124,7 +124,7 @@
     @Test
     public void buildReportFeatures_basicPlaybackAudioSystem_1_4() {
         HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
                         HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM), Constants.RC_PROFILE_TV,
                 Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
index e370018..b1998f5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
@@ -390,7 +390,7 @@
         assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus);
         assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
@@ -436,7 +436,7 @@
         assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
                 HdmiControlManager.POWER_STATUS_UNKNOWN);
         assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
@@ -482,7 +482,7 @@
     @Test
     public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() {
         int logicalAddress = Constants.ADDR_PLAYBACK_1;
-        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
                         cecVersion));
@@ -512,7 +512,7 @@
     @Test
     public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() {
         int logicalAddress = Constants.ADDR_PLAYBACK_1;
-        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
         mHdmiCecNetwork.handleCecMessage(
                 HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
                         cecVersion, Collections.emptyList(),
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
index 670d512..06373c2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
@@ -62,7 +62,7 @@
     private FakeNativeWrapper mNativeWrapper;
     private TestLooper mTestLooper = new TestLooper();
     private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
-    private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+    private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
     @Mock
     private IPowerManager mIPowerManagerMock;
     @Mock
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 2513807..c2268c5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -246,7 +246,7 @@
     public void initialPowerStatus_normalBoot_goToStandby_doesNotBroadcastsPowerStatus_1_4() {
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
 
         mHdmiControlService.setControlEnabled(true);
         mNativeWrapper.clearResultMessages();
@@ -442,17 +442,17 @@
                 null);
         mHdmiControlService.setControlEnabled(true);
         assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
     public void getCecVersion_1_4() {
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiControlService.setControlEnabled(true);
         assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
     }
 
     @Test
@@ -469,10 +469,10 @@
     public void getCecVersion_change() {
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiControlService.setControlEnabled(true);
         assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
 
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
@@ -486,7 +486,7 @@
     public void handleGiveFeatures_cec14_featureAbort() {
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiControlService.setControlEnabled(true);
         mTestLooper.dispatchAll();
 
@@ -526,7 +526,7 @@
         mNativeWrapper.clearResultMessages();
         mHdmiControlService.getHdmiCecConfig().setIntValue(
                 HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
         mHdmiControlService.setControlEnabled(true);
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mTestLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
index 5316ef6..9f0cdd5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
@@ -536,49 +536,49 @@
     @Test
     public void isEligibleAddressForCecVersion_1_4() {
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_TV)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_RECORDER_1)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_RECORDER_2)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_TUNER_1)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_PLAYBACK_1)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_AUDIO_SYSTEM)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_TUNER_2)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_TUNER_3)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_PLAYBACK_2)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_RECORDER_3)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_TUNER_4)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_PLAYBACK_3)).isTrue();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_BACKUP_1)).isFalse();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_BACKUP_2)).isFalse();
         assertThat(HdmiUtils.isEligibleAddressForCecVersion(
-                HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+                HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
                 Constants.ADDR_SPECIFIC_USE)).isTrue();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
index c4d1211..98d6452 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
@@ -95,13 +95,24 @@
 
     static class MockInjector extends RebootEscrowManager.Injector {
         private final IRebootEscrow mRebootEscrow;
+        private final RebootEscrowProviderInterface mRebootEscrowProvider;
         private final UserManager mUserManager;
         private final MockableRebootEscrowInjected mInjected;
 
-        MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow,
+        MockInjector(Context context, UserManager userManager,
+                IRebootEscrow rebootEscrow,
                 MockableRebootEscrowInjected injected) {
             super(context);
             mRebootEscrow = rebootEscrow;
+
+            RebootEscrowProviderHalImpl.Injector halInjector =
+                    new RebootEscrowProviderHalImpl.Injector() {
+                        @Override
+                        public IRebootEscrow getRebootEscrow() {
+                            return mRebootEscrow;
+                        }
+                    };
+            mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector);
             mUserManager = userManager;
             mInjected = injected;
         }
@@ -112,8 +123,8 @@
         }
 
         @Override
-        public IRebootEscrow getRebootEscrow() {
-            return mRebootEscrow;
+        public RebootEscrowProviderInterface getRebootEscrowProvider() {
+            return mRebootEscrowProvider;
         }
 
         @Override
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 11d00f0..5719dd2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -173,6 +173,7 @@
                 /* installSource */ installSource,
                 /* sessionParams */ params,
                 /* createdMillis */ 0L,
+                /* committedMillis */ 0L,
                 /* stageDir */ mTmpDir,
                 /* stageCid */ null,
                 /* files */ null,
diff --git a/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
new file mode 100644
index 0000000..4870c9e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.pm;
+
+import android.content.Context;
+import android.content.pm.PackageInstaller;
+import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.internal.os.BackgroundThread;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+@Presubmit
+@RunWith(JUnit4.class)
+public class StagingManagerTest {
+    @Rule
+    public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+    private File mTmpDir;
+    private StagingManager mStagingManager;
+
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        StorageManager storageManager = Mockito.mock(StorageManager.class);
+        Context context = Mockito.mock(Context.class);
+        when(storageManager.isCheckpointSupported()).thenReturn(true);
+        when(context.getSystemService(eq(Context.POWER_SERVICE))).thenReturn(null);
+        when(context.getSystemService(eq(Context.STORAGE_SERVICE))).thenReturn(storageManager);
+
+        mTmpDir = mTemporaryFolder.newFolder("StagingManagerTest");
+        mStagingManager = new StagingManager(context, null);
+    }
+
+    /**
+     * Tests that sessions committed later shouldn't cause earlier ones to fail the overlapping
+     * check.
+     */
+    @Test
+    public void checkNonOverlappingWithStagedSessions_laterSessionShouldNotFailEarlierOnes()
+            throws Exception {
+        // Create 2 sessions with overlapping packages
+        PackageInstallerSession session1 = createSession(111, "com.foo", 1);
+        PackageInstallerSession session2 = createSession(222, "com.foo", 2);
+
+        mStagingManager.createSession(session1);
+        mStagingManager.createSession(session2);
+        // Session1 should not fail in spite of the overlapping packages
+        mStagingManager.checkNonOverlappingWithStagedSessions(session1);
+        // Session2 should fail due to overlapping packages
+        assertThrows(PackageManagerException.class,
+                () -> mStagingManager.checkNonOverlappingWithStagedSessions(session2));
+    }
+
+    private PackageInstallerSession createSession(int sessionId, String packageName,
+            long committedMillis) {
+        PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+        params.isStaged = true;
+
+        InstallSource installSource = InstallSource.create("testInstallInitiator",
+                "testInstallOriginator", "testInstaller", "testAttributionTag");
+
+        PackageInstallerSession session = new PackageInstallerSession(
+                /* callback */ null,
+                /* context */ null,
+                /* pm */ null,
+                /* sessionProvider */ null,
+                /* looper */ BackgroundThread.getHandler().getLooper(),
+                /* stagingManager */ null,
+                /* sessionId */ sessionId,
+                /* userId */ 456,
+                /* installerUid */ -1,
+                /* installSource */ installSource,
+                /* sessionParams */ params,
+                /* createdMillis */ 0L,
+                /* committedMillis */ committedMillis,
+                /* stageDir */ mTmpDir,
+                /* stageCid */ null,
+                /* files */ null,
+                /* checksums */ null,
+                /* prepared */ true,
+                /* committed */ true,
+                /* destroyed */ false,
+                /* sealed */ false,  // Setting to true would trigger some PM logic.
+                /* childSessionIds */ null,
+                /* parentSessionId */ -1,
+                /* isReady */ false,
+                /* isFailed */ false,
+                /* isApplied */false,
+                /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.STAGED_SESSION_NO_ERROR,
+                /* stagedSessionErrorMessage */ "no error");
+
+        session = spy(session);
+        doReturn(packageName).when(session).getPackageName();
+        return session;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS b/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS
new file mode 100644
index 0000000..3880038
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/recoverysystem/OWNERS
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 45b6bce..f7c655f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1501,20 +1501,6 @@
     }
 
     @Test
-    public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
-            throws Exception {
-        final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
-        sbn.getNotification().flags =
-                Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
-        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
-                sbn.getId(), sbn.getNotification(), sbn.getUserId());
-        mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
-        waitForIdle();
-        verify(mListeners, times(1)).notifyPostedLocked(any(), any());
-        verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
-    }
-
-    @Test
     public void testUserInitiatedClearAll_noLeak() throws Exception {
         final NotificationRecord n = generateNotificationRecord(
                 mTestNotificationChannel, 1, "group", true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index eebc207..61911b3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -22,8 +22,13 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
+import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
 
@@ -40,6 +45,7 @@
 
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
 
@@ -253,6 +259,68 @@
         assertThat(newActivityBounds.height()).isEqualTo(activityBounds.height());
     }
 
+    @Test
+    public void testPlaceImeContainer_reparentToTargetDisplayAreaGroup() {
+        setupImeWindow();
+        final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
+        final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);
+
+        // By default, the ime container is attached to DC as defined in DAPolicy.
+        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
+        assertThat(mDisplay.findAreaForToken(imeToken)).isEqualTo(imeContainer);
+
+        final WindowState firstActivityWin =
+                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
+                        "firstActivityWin");
+        spyOn(firstActivityWin);
+        final WindowState secondActivityWin =
+                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mSecondActivity,
+                        "firstActivityWin");
+        spyOn(secondActivityWin);
+
+        // firstActivityWin should be the target
+        doReturn(true).when(firstActivityWin).canBeImeTarget();
+        doReturn(false).when(secondActivityWin).canBeImeTarget();
+
+        WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);
+
+        assertThat(imeTarget).isEqualTo(firstActivityWin);
+        verify(mFirstRoot).placeImeContainer(imeContainer);
+        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mFirstRoot);
+        assertThat(imeContainer.getParent().asDisplayArea().mFeatureId)
+                .isEqualTo(FEATURE_IME_PLACEHOLDER);
+        assertThat(mDisplay.findAreaForToken(imeToken)).isNull();
+        assertThat(mFirstRoot.findAreaForToken(imeToken)).isEqualTo(imeContainer);
+        assertThat(mSecondRoot.findAreaForToken(imeToken)).isNull();
+
+        // secondActivityWin should be the target
+        doReturn(false).when(firstActivityWin).canBeImeTarget();
+        doReturn(true).when(secondActivityWin).canBeImeTarget();
+
+        imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);
+
+        assertThat(imeTarget).isEqualTo(secondActivityWin);
+        verify(mSecondRoot).placeImeContainer(imeContainer);
+        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mSecondRoot);
+        assertThat(imeContainer.getParent().asDisplayArea().mFeatureId)
+                .isEqualTo(FEATURE_IME_PLACEHOLDER);
+        assertThat(mDisplay.findAreaForToken(imeToken)).isNull();
+        assertThat(mFirstRoot.findAreaForToken(imeToken)).isNull();
+        assertThat(mSecondRoot.findAreaForToken(imeToken)).isEqualTo(imeContainer);
+    }
+
+    private void setupImeWindow() {
+        final WindowState imeWindow = createWindow(null /* parent */,
+                TYPE_INPUT_METHOD, mDisplay, "mImeWindow");
+        imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+        mDisplay.mInputMethodWindow = imeWindow;
+    }
+
+    private WindowToken tokenOfType(int type) {
+        return new WindowToken(mWm, new Binder(), type, false /* persistOnEmpty */,
+                mDisplay, false /* ownerCanManageAppTokens */);
+    }
+
     /** Display with two {@link DisplayAreaGroup}. Each of them take half of the screen. */
     private static class DualDisplayContent extends TestDisplayContent {
         final DisplayAreaGroup mFirstRoot;
@@ -356,6 +424,11 @@
                                     .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                                     .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
                                     .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
+                                    .build())
+                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
+                                    wmService.mPolicy,
+                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
+                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
                                     .build());
 
             // First
@@ -367,7 +440,12 @@
             firstTdaList.add(firstTaskDisplayArea);
             DisplayAreaPolicyBuilder.HierarchyBuilder firstHierarchy =
                     new DisplayAreaPolicyBuilder.HierarchyBuilder(firstRoot)
-                            .setTaskDisplayAreas(firstTdaList);
+                            .setTaskDisplayAreas(firstTdaList)
+                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
+                                    wmService.mPolicy,
+                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
+                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
+                                    .build());
 
             // Second
             final RootDisplayArea secondRoot = new DisplayAreaGroup(wmService, "SecondRoot",
@@ -378,7 +456,12 @@
             secondTdaList.add(secondTaskDisplayArea);
             DisplayAreaPolicyBuilder.HierarchyBuilder secondHierarchy =
                     new DisplayAreaPolicyBuilder.HierarchyBuilder(secondRoot)
-                            .setTaskDisplayAreas(secondTdaList);
+                            .setTaskDisplayAreas(secondTdaList)
+                            .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(
+                                    wmService.mPolicy,
+                                    "ImePlaceholder", FEATURE_IME_PLACEHOLDER)
+                                    .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
+                                    .build());
 
             return new DisplayAreaPolicyBuilder()
                     .setRootHierarchy(rootHierarchy)
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 6dd23ba..ea57588 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -378,23 +378,25 @@
         // Simulate giving up the swipe up gesture to keep the original activity as top.
         mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
         // The rotation transform should be cleared after updating orientation with display.
-        assertFalse(activity.hasFixedRotationTransform());
-        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
+        assertTopFixedRotationLaunchingAppCleared(activity);
 
         // Simulate swiping up recents (home) in different rotation.
         final ActivityRecord home = mDefaultDisplay.getDefaultTaskDisplayArea().getHomeActivity();
-        mDefaultDisplay.setFixedRotationLaunchingApp(home, (mDefaultDisplay.getRotation() + 1) % 4);
-        mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
-                mDefaultDisplay.getDisplayId());
-        initializeRecentsAnimationController(mController, home);
-        assertTrue(home.hasFixedRotationTransform());
+        startRecentsInDifferentRotation(home);
 
+        // If the recents activity becomes the top running activity (e.g. the original top activity
+        // is either finishing or moved to back during recents animation), the display orientation
+        // will be determined by it so the fixed rotation must be cleared.
+        activity.finishing = true;
+        mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
+        assertTopFixedRotationLaunchingAppCleared(home);
+
+        startRecentsInDifferentRotation(home);
         // Assume recents activity becomes invisible for some reason (e.g. screen off).
         home.setVisible(false);
         mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
         // Although there won't be a transition finish callback, the fixed rotation must be cleared.
-        assertFalse(home.hasFixedRotationTransform());
-        assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
+        assertTopFixedRotationLaunchingAppCleared(home);
     }
 
     @Test
@@ -508,6 +510,21 @@
         return homeActivity;
     }
 
+    private void startRecentsInDifferentRotation(ActivityRecord recentsActivity) {
+        final DisplayContent displayContent = recentsActivity.mDisplayContent;
+        displayContent.setFixedRotationLaunchingApp(recentsActivity,
+                (displayContent.getRotation() + 1) % 4);
+        mController = new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
+                displayContent.getDisplayId());
+        initializeRecentsAnimationController(mController, recentsActivity);
+        assertTrue(recentsActivity.hasFixedRotationTransform());
+    }
+
+    private static void assertTopFixedRotationLaunchingAppCleared(ActivityRecord activity) {
+        assertFalse(activity.hasFixedRotationTransform());
+        assertFalse(activity.mDisplayContent.hasTopFixedRotationLaunchingApp());
+    }
+
     private static void initializeRecentsAnimationController(RecentsAnimationController controller,
             ActivityRecord activity) {
         controller.initialize(activity.getActivityType(), new SparseBooleanArray(), activity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index f79e4cc..226c71a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -90,12 +90,9 @@
 @Presubmit
 @RunWith(WindowTestRunner.class)
 public class RootActivityContainerTests extends WindowTestsBase {
-    private Task mFullscreenStack;
 
     @Before
     public void setUp() throws Exception {
-        mFullscreenStack = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         doNothing().when(mAtm).updateSleepIfNeededLocked();
     }
 
@@ -117,50 +114,54 @@
      */
     @Test
     public void testReplacingTaskInPinnedStack() {
+        Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
-                .setTask(mFullscreenStack).build();
+                .setTask(fullscreenTask).build();
         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
-                .setTask(mFullscreenStack).build();
+                .setTask(fullscreenTask).build();
 
-        mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
+        fullscreenTask.moveToFront("testReplacingTaskInPinnedStack");
 
         // Ensure full screen stack has both tasks.
-        ensureStackPlacement(mFullscreenStack, firstActivity, secondActivity);
+        ensureStackPlacement(fullscreenTask, firstActivity, secondActivity);
 
         // Move first activity to pinned stack.
         mRootWindowContainer.moveActivityToPinnedRootTask(firstActivity, "initialMove");
 
-        final TaskDisplayArea taskDisplayArea = mFullscreenStack.getDisplayArea();
+        final TaskDisplayArea taskDisplayArea = fullscreenTask.getDisplayArea();
         Task pinnedStack = taskDisplayArea.getRootPinnedTask();
         // Ensure a task has moved over.
         ensureStackPlacement(pinnedStack, firstActivity);
-        ensureStackPlacement(mFullscreenStack, secondActivity);
+        ensureStackPlacement(fullscreenTask, secondActivity);
 
         // Move second activity to pinned stack.
         mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity, "secondMove");
 
         // Need to get stacks again as a new instance might have been created.
         pinnedStack = taskDisplayArea.getRootPinnedTask();
-        mFullscreenStack = taskDisplayArea.getRootTask(WINDOWING_MODE_FULLSCREEN,
+        fullscreenTask = taskDisplayArea.getRootTask(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD);
         // Ensure stacks have swapped tasks.
         ensureStackPlacement(pinnedStack, secondActivity);
-        ensureStackPlacement(mFullscreenStack, firstActivity);
+        ensureStackPlacement(fullscreenTask, firstActivity);
     }
 
     @Test
     public void testMovingBottomMostStackActivityToPinnedStack() {
+        final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
-                .setTask(mFullscreenStack).build();
+                .setTask(fullscreenTask).build();
         final Task task = firstActivity.getTask();
 
         final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
-                .setTask(mFullscreenStack).build();
+                .setTask(fullscreenTask).build();
 
-        mFullscreenStack.moveTaskToBack(task);
+        fullscreenTask.moveTaskToBack(task);
 
         // Ensure full screen stack has both tasks.
-        ensureStackPlacement(mFullscreenStack, firstActivity, secondActivity);
+        ensureStackPlacement(fullscreenTask, firstActivity, secondActivity);
         assertEquals(task.getTopMostActivity(), secondActivity);
         firstActivity.setState(STOPPED, "testMovingBottomMostStackActivityToPinnedStack");
 
@@ -171,21 +172,20 @@
         assertTrue(firstActivity.mRequestForceTransition);
     }
 
-    private static void ensureStackPlacement(Task stack, ActivityRecord... activities) {
-        final Task task = stack.getBottomMostTask();
-        final ArrayList<ActivityRecord> stackActivities = new ArrayList<>();
+    private static void ensureStackPlacement(Task task, ActivityRecord... activities) {
+        final ArrayList<ActivityRecord> taskActivities = new ArrayList<>();
 
-        task.forAllActivities((Consumer<ActivityRecord>) stackActivities::add, false);
+        task.forAllActivities((Consumer<ActivityRecord>) taskActivities::add, false);
 
-        assertEquals("Expecting " + Arrays.deepToString(activities) + " got " + stackActivities,
-                stackActivities.size(), activities != null ? activities.length : 0);
+        assertEquals("Expecting " + Arrays.deepToString(activities) + " got " + taskActivities,
+                taskActivities.size(), activities != null ? activities.length : 0);
 
         if (activities == null) {
             return;
         }
 
         for (ActivityRecord activity : activities) {
-            assertTrue(stackActivities.contains(activity));
+            assertTrue(taskActivities.contains(activity));
         }
     }
 
@@ -419,19 +419,18 @@
      */
     @Test
     public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
-        // Create stack/task on default display.
+        // Create tasks on default display.
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        final Task targetStack = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+        final Task targetRootTask = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */);
-        final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
+        final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetRootTask).build();
 
         // Create Recents on secondary display.
         final TestDisplayContent secondDisplay = addNewDisplayContentAt(
                 DisplayContent.POSITION_TOP);
-        final Task stack = secondDisplay.getDefaultTaskDisplayArea()
+        final Task rootTask = secondDisplay.getDefaultTaskDisplayArea()
                 .createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
-        final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build();
-        new ActivityBuilder(mAtm).setTask(task).build();
+        new ActivityBuilder(mAtm).setTask(rootTask).build();
 
         final String reason = "findTaskToMoveToFront";
         mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
@@ -446,25 +445,24 @@
      */
     @Test
     public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
-        // Create a stack at bottom.
+        // Create a root task at bottom.
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+        final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
-        final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
-        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
-        taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/);
+        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(rootTask).build();
+        taskDisplayArea.positionChildAt(POSITION_BOTTOM, rootTask, false /*includingParents*/);
 
-        // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
-        // is the current top focused stack.
-        assertFalse(targetStack.isTopStackInDisplayArea());
-        doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+        // Assume the task is not at the topmost position (e.g. behind always-on-top stacks) but it
+        // is the current top focused task.
+        assertFalse(rootTask.isTopStackInDisplayArea());
+        doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
 
-        // Use the stack as target to resume.
+        // Use the task as target to resume.
         mRootWindowContainer.resumeFocusedTasksTopActivities(
-                targetStack, activity, null /* targetOptions */);
+                rootTask, activity, null /* targetOptions */);
 
-        // Verify the target stack should resume its activity.
-        verify(targetStack, times(1)).resumeTopActivityUncheckedLocked(
+        // Verify the target task should resume its activity.
+        verify(rootTask, times(1)).resumeTopActivityUncheckedLocked(
                 eq(activity), eq(null /* targetOptions */));
     }
 
@@ -474,7 +472,6 @@
      */
     @Test
     public void testResumeFocusedStacksStartsHomeActivity_NoActivities() {
-        mFullscreenStack.removeIfPossible();
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         taskDisplayArea.getRootHomeTask().removeIfPossible();
         taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
@@ -496,7 +493,6 @@
      */
     @Test
     public void testResumeFocusedStacksStartsHomeActivity_ActivityOnSecondaryScreen() {
-        mFullscreenStack.removeIfPossible();
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         taskDisplayArea.getRootHomeTask().removeIfPossible();
         taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
@@ -506,8 +502,7 @@
                 DisplayContent.POSITION_TOP);
         final Task rootTask = secondDisplay.getDefaultTaskDisplayArea().createRootTask(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
-        new ActivityBuilder(mAtm).setTask(task).build();
+        new ActivityBuilder(mAtm).setTask(rootTask).build();
 
         doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), any());
 
@@ -526,44 +521,44 @@
      */
     @Test
     public void testResumeActivityLingeringTransition() {
-        // Create a stack at top.
+        // Create a root task at top.
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+        final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
-        final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
-        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(rootTask).setOnTop(true).build();
         activity.setState(ActivityState.RESUMED, "test");
 
-        // Assume the stack is at the topmost position
-        assertTrue(targetStack.isTopStackInDisplayArea());
+        // Assume the task is at the topmost position
+        assertTrue(rootTask.isTopStackInDisplayArea());
 
-        // Use the stack as target to resume.
+        // Use the task as target to resume.
         mRootWindowContainer.resumeFocusedTasksTopActivities();
 
         // Verify the lingering app transition is being executed because it's already resumed
-        verify(targetStack, times(1)).executeAppTransition(any());
+        verify(rootTask, times(1)).executeAppTransition(any());
     }
 
     @Test
     public void testResumeActivityLingeringTransition_notExecuted() {
-        // Create a stack at bottom.
+        // Create a root task at bottom.
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
-        final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+        final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, false /* onTop */));
-        final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
-        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(rootTask).setOnTop(true).build();
         activity.setState(ActivityState.RESUMED, "test");
-        taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/);
+        taskDisplayArea.positionChildAt(POSITION_BOTTOM, rootTask, false /*includingParents*/);
 
-        // Assume the stack is at the topmost position
-        assertFalse(targetStack.isTopStackInDisplayArea());
-        doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+        // Assume the task is at the topmost position
+        assertFalse(rootTask.isTopStackInDisplayArea());
+        doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
 
-        // Use the stack as target to resume.
+        // Use the task as target to resume.
         mRootWindowContainer.resumeFocusedTasksTopActivities();
 
         // Verify the lingering app transition is being executed because it's already resumed
-        verify(targetStack, never()).executeAppTransition(any());
+        verify(rootTask, never()).executeAppTransition(any());
     }
 
     /**
@@ -889,7 +884,9 @@
 
     @Test
     public void testSwitchUser_missingHomeRootTask() {
-        doReturn(mFullscreenStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+        final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        doReturn(fullscreenTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
 
         final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
         Task homeStack = taskDisplayArea.getRootHomeTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 4041412..e58c162 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -47,7 +47,7 @@
 import org.junit.runner.RunWith;
 
 /**
- * Tests for the {@link ActivityStack} class.
+ * Tests for the {@link Task} class.
  *
  * Build/Install/Run:
  *  atest WmTests:TaskStackTests
@@ -82,36 +82,29 @@
     }
 
     @Test
-    public void testClosingAppDifferentStackOrientation() {
-        final Task stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
-        task1.addChild(activity1, 0);
+    public void testClosingAppDifferentTaskOrientation() {
+        final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
         activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
-        final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
-        task2.addChild(activity2, 0);
+        final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
         activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
 
-        assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
+        final WindowContainer parent = activity1.getTask().getParent();
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, parent.getOrientation());
         mDisplayContent.mClosingApps.add(activity2);
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
+        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, parent.getOrientation());
     }
 
     @Test
-    public void testMoveTaskToBackDifferentStackOrientation() {
-        final Task stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task1 = createTaskInStack(stack, 0 /* userId */);
-        ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
-        task1.addChild(activity1, 0);
+    public void testMoveTaskToBackDifferentTaskOrientation() {
+        final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
         activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
-        final Task task2 = createTaskInStack(stack, 1 /* userId */);
-        ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
-        task2.addChild(activity2, 0);
+        final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
         activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
-        assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
+
+        final WindowContainer parent = activity1.getTask().getParent();
+        assertEquals(SCREEN_ORIENTATION_PORTRAIT, parent.getOrientation());
     }
 
     @Test
@@ -215,8 +208,7 @@
 
     @Test
     public void testActivityAndTaskGetsProperType() {
-        final Task stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task1 = createTaskInStack(stack, 0 /* userId */);
+        final Task task1 = new TaskBuilder(mSupervisor).build();
         ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
 
         // First activity should become standard
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index aa36e47..3815326 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -184,10 +184,12 @@
     private static class ActivityData {
         private final String mTaskRootPackage;
         private final String mTaskRootClass;
+        private final String mUsageSourcePackage;
         public int lastEvent = Event.NONE;
-        private ActivityData(String taskRootPackage, String taskRootClass) {
+        private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) {
             mTaskRootPackage = taskRootPackage;
             mTaskRootClass = taskRootClass;
+            mUsageSourcePackage = sourcePackage;
         }
     }
 
@@ -840,23 +842,25 @@
                                     .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
                     // check if this activity has already been resumed
                     if (mVisibleActivities.get(event.mInstanceId) != null) break;
-                    final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
-                            event.mTaskRootClass);
-                    resumedData.lastEvent = Event.ACTIVITY_RESUMED;
-                    mVisibleActivities.put(event.mInstanceId, resumedData);
+                    final String usageSourcePackage;
+                    switch(mUsageSource) {
+                        case USAGE_SOURCE_CURRENT_ACTIVITY:
+                            usageSourcePackage = event.mPackage;
+                            break;
+                        case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+                        default:
+                            usageSourcePackage = event.mTaskRootPackage;
+                            break;
+                    }
                     try {
-                        switch(mUsageSource) {
-                            case USAGE_SOURCE_CURRENT_ACTIVITY:
-                                mAppTimeLimit.noteUsageStart(event.mPackage, userId);
-                                break;
-                            case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
-                            default:
-                                mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId);
-                                break;
-                        }
+                        mAppTimeLimit.noteUsageStart(usageSourcePackage, userId);
                     } catch (IllegalArgumentException iae) {
                         Slog.e(TAG, "Failed to note usage start", iae);
                     }
+                    final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
+                            event.mTaskRootClass, usageSourcePackage);
+                    resumedData.lastEvent = Event.ACTIVITY_RESUMED;
+                    mVisibleActivities.put(event.mInstanceId, resumedData);
                     break;
                 case Event.ACTIVITY_PAUSED:
                     final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
@@ -928,15 +932,7 @@
                         event.mTaskRootClass = prevData.mTaskRootClass;
                     }
                     try {
-                        switch(mUsageSource) {
-                            case USAGE_SOURCE_CURRENT_ACTIVITY:
-                                mAppTimeLimit.noteUsageStop(event.mPackage, userId);
-                                break;
-                            case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
-                            default:
-                                mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId);
-                                break;
-                        }
+                        mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId);
                     } catch (IllegalArgumentException iae) {
                         Slog.w(TAG, "Failed to note usage stop", iae);
                     }
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
new file mode 100644
index 0000000..e5d0370
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
@@ -0,0 +1,2 @@
+ytai@google.com
+elaurent@google.com
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 4bf93a2..283fae5 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -1038,6 +1038,7 @@
             if (mModule != null) {
                 mModule.detach();
                 mModule = null;
+                mServiceDisabled = false;
             }
         }
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index df0b9ac..31a1249 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1516,6 +1516,16 @@
     public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4;
 
     /**
+     * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE}
+     * to indicate that default subscription for data/sms/voice is now determined, that
+     * it should dismiss any dialog or pop-ups that is asking user to select default sub.
+     * This is used when, for example, opportunistic subscription is configured. At that
+     * time the primary becomes default sub there's no need to ask user to select anymore.
+     * @hide
+     */
+    public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS = 5;
+
+    /**
      * Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED}
      * to indicate if the SIM combination in DSDS has limitation or compatible issue.
      * e.g. two CDMA SIMs may disrupt each other's voice call in certain scenarios.
diff --git a/test-mock/src/android/test/mock/OWNERS b/test-mock/src/android/test/mock/OWNERS
new file mode 100644
index 0000000..9551245
--- /dev/null
+++ b/test-mock/src/android/test/mock/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+*
diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp
index 7dc44fa..c14e705 100644
--- a/tests/Compatibility/Android.bp
+++ b/tests/Compatibility/Android.bp
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-android_test {
+android_test_helper_app {
     name: "AppCompatibilityTest",
     static_libs: ["androidx.test.rules"],
     // Include all test java files.
diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
new file mode 100644
index 0000000..6770066
--- /dev/null
+++ b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.InetAddresses.parseNumericAddress
+import android.os.Build
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertFieldCountEquals
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.net.InetAddress
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
+
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) // TcpKeepalivePacketData added to SDK in S
+class TcpKeepalivePacketDataTest {
+    private fun makeData(
+        srcAddress: InetAddress = parseNumericAddress("192.0.2.123"),
+        srcPort: Int = 1234,
+        dstAddress: InetAddress = parseNumericAddress("192.0.2.231"),
+        dstPort: Int = 4321,
+        data: ByteArray = byteArrayOf(1, 2, 3),
+        tcpSeq: Int = 135,
+        tcpAck: Int = 246,
+        tcpWnd: Int = 1234,
+        tcpWndScale: Int = 2,
+        ipTos: Int = 0x12,
+        ipTtl: Int = 10
+    ) = TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data, tcpSeq, tcpAck,
+            tcpWnd, tcpWndScale, ipTos, ipTtl)
+
+    @Test
+    fun testEquals() {
+        val data1 = makeData()
+        val data2 = makeData()
+        assertEquals(data1, data2)
+        assertEquals(data1.hashCode(), data2.hashCode())
+    }
+
+    @Test
+    fun testNotEquals() {
+        assertNotEquals(makeData(srcAddress = parseNumericAddress("192.0.2.124")), makeData())
+        assertNotEquals(makeData(srcPort = 1235), makeData())
+        assertNotEquals(makeData(dstAddress = parseNumericAddress("192.0.2.232")), makeData())
+        assertNotEquals(makeData(dstPort = 4322), makeData())
+        // .equals does not test .packet, as it should be generated from the other fields
+        assertNotEquals(makeData(tcpSeq = 136), makeData())
+        assertNotEquals(makeData(tcpAck = 247), makeData())
+        assertNotEquals(makeData(tcpWnd = 1235), makeData())
+        assertNotEquals(makeData(tcpWndScale = 3), makeData())
+        assertNotEquals(makeData(ipTos = 0x14), makeData())
+        assertNotEquals(makeData(ipTtl = 11), makeData())
+
+        // Update above assertions if field is added
+        assertFieldCountEquals(5, KeepalivePacketData::class.java)
+        assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+    }
+
+    @Test
+    fun testParcelUnparcel() {
+        assertParcelSane(makeData(), fieldCount = 6) { a, b ->
+            // .equals() does not verify .packet
+            a == b && a.packet contentEquals b.packet
+        }
+    }
+
+    @Test
+    fun testToString() {
+        val data = makeData()
+        val str = data.toString()
+
+        assertTrue(str.contains(data.srcAddress.hostAddress))
+        assertTrue(str.contains(data.srcPort.toString()))
+        assertTrue(str.contains(data.dstAddress.hostAddress))
+        assertTrue(str.contains(data.dstPort.toString()))
+        // .packet not included in toString()
+        assertTrue(str.contains(data.tcpSeq.toString()))
+        assertTrue(str.contains(data.tcpAck.toString()))
+        assertTrue(str.contains(data.tcpWindow.toString()))
+        assertTrue(str.contains(data.tcpWindowScale.toString()))
+        assertTrue(str.contains(data.ipTos.toString()))
+        assertTrue(str.contains(data.ipTtl.toString()))
+
+        // Update above assertions if field is added
+        assertFieldCountEquals(5, KeepalivePacketData::class.java)
+        assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+    }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
similarity index 65%
rename from tests/net/java/android/net/TcpKeepalivePacketDataTest.java
rename to tests/net/java/android/net/KeepalivePacketDataUtilTest.java
index c5b25bd..fc739fb 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/KeepalivePacketDataUtilTest.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,8 +20,11 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.net.util.KeepalivePacketDataUtil;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -31,7 +34,7 @@
 import java.nio.ByteBuffer;
 
 @RunWith(JUnit4.class)
-public final class TcpKeepalivePacketDataTest {
+public final class KeepalivePacketDataUtilTest {
     private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
     private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
 
@@ -39,7 +42,7 @@
     public void setUp() {}
 
     @Test
-    public void testV4TcpKeepalivePacket() throws Exception {
+    public void testFromTcpKeepaliveStableParcelable() throws Exception {
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int seq = 0x11111111;
@@ -61,7 +64,7 @@
         testInfo.tos = tos;
         testInfo.ttl = ttl;
         try {
-            resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
+            resultData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
         } catch (InvalidPacketException e) {
             fail("InvalidPacketException: " + e);
         }
@@ -72,8 +75,8 @@
         assertEquals(testInfo.dstPort, resultData.getDstPort());
         assertEquals(testInfo.seq, resultData.tcpSeq);
         assertEquals(testInfo.ack, resultData.tcpAck);
-        assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
-        assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
+        assertEquals(testInfo.rcvWnd, resultData.tcpWindow);
+        assertEquals(testInfo.rcvWndScale, resultData.tcpWindowScale);
         assertEquals(testInfo.tos, resultData.ipTos);
         assertEquals(testInfo.ttl, resultData.ipTtl);
 
@@ -113,7 +116,7 @@
     //TODO: add ipv6 test when ipv6 supported
 
     @Test
-    public void testParcel() throws Exception {
+    public void testToTcpKeepaliveStableParcelable() throws Exception {
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int sequence = 0x11111111;
@@ -135,8 +138,8 @@
         testInfo.ttl = ttl;
         TcpKeepalivePacketData testData = null;
         TcpKeepalivePacketDataParcelable resultData = null;
-        testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
-        resultData = testData.toStableParcelable();
+        testData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
+        resultData = KeepalivePacketDataUtil.toStableParcelable(testData);
         assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
         assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
         assertEquals(resultData.srcPort, srcPort);
@@ -154,4 +157,49 @@
                 + " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}";
         assertEquals(expected, resultData.toString());
     }
+
+    @Test
+    public void testParseTcpKeepalivePacketData() throws Exception {
+        final int srcPort = 1234;
+        final int dstPort = 4321;
+        final int sequence = 0x11111111;
+        final int ack = 0x22222222;
+        final int wnd = 4800;
+        final int wndScale = 2;
+        final int tos = 4;
+        final int ttl = 64;
+        final TcpKeepalivePacketDataParcelable testParcel = new TcpKeepalivePacketDataParcelable();
+        testParcel.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testParcel.srcPort = srcPort;
+        testParcel.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testParcel.dstPort = dstPort;
+        testParcel.seq = sequence;
+        testParcel.ack = ack;
+        testParcel.rcvWnd = wnd;
+        testParcel.rcvWndScale = wndScale;
+        testParcel.tos = tos;
+        testParcel.ttl = ttl;
+
+        final KeepalivePacketData testData =
+                KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+        final TcpKeepalivePacketDataParcelable parsedParcelable =
+                KeepalivePacketDataUtil.parseTcpKeepalivePacketData(testData);
+        final TcpKeepalivePacketData roundTripData =
+                KeepalivePacketDataUtil.fromStableParcelable(parsedParcelable);
+
+        // Generated packet is the same, but rcvWnd / wndScale will differ if scale is non-zero
+        assertTrue(testData.getPacket().length > 0);
+        assertArrayEquals(testData.getPacket(), roundTripData.getPacket());
+
+        testParcel.rcvWndScale = 0;
+        final KeepalivePacketData noScaleTestData =
+                KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+        final TcpKeepalivePacketDataParcelable noScaleParsedParcelable =
+                KeepalivePacketDataUtil.parseTcpKeepalivePacketData(noScaleTestData);
+        final TcpKeepalivePacketData noScaleRoundTripData =
+                KeepalivePacketDataUtil.fromStableParcelable(noScaleParsedParcelable);
+        assertEquals(noScaleTestData, noScaleRoundTripData);
+        assertTrue(noScaleTestData.getPacket().length > 0);
+        assertArrayEquals(noScaleTestData.getPacket(), noScaleRoundTripData.getPacket());
+    }
 }
diff --git a/tools/split-select/OWNERS b/tools/split-select/OWNERS
new file mode 100644
index 0000000..6c50ede
--- /dev/null
+++ b/tools/split-select/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/res/OWNERS
\ No newline at end of file
diff --git a/tools/stats_log_api_gen/.clang-format b/tools/stats_log_api_gen/.clang-format
deleted file mode 100644
index cead3a0..0000000
--- a/tools/stats_log_api_gen/.clang-format
+++ /dev/null
@@ -1,17 +0,0 @@
-BasedOnStyle: Google
-AllowShortIfStatementsOnASingleLine: true
-AllowShortFunctionsOnASingleLine: false
-AllowShortLoopsOnASingleLine: true
-BinPackArguments: true
-BinPackParameters: true
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-ContinuationIndentWidth: 8
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-AccessModifierOffset: -4
-IncludeCategories:
-  - Regex:    '^"Log\.h"'
-    Priority:    -1
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
deleted file mode 100644
index ab8702b..0000000
--- a/tools/stats_log_api_gen/Android.bp
+++ /dev/null
@@ -1,150 +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.
-//
-
-// ==========================================================
-// Build the host executable: stats-log-api-gen
-// ==========================================================
-cc_binary_host {
-    name: "stats-log-api-gen",
-    srcs: [
-        "Collation.cpp",
-        "java_writer.cpp",
-        "java_writer_q.cpp",
-        "main.cpp",
-        "native_writer.cpp",
-        "utils.cpp",
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    shared_libs: [
-        "libstats_proto_host",
-        "libprotobuf-cpp-full",
-        "libbase",
-    ],
-
-    proto: {
-        type: "full",
-    },
-}
-
-// ==========================================================
-// Build the host test executable: stats-log-api-gen
-// ==========================================================
-cc_test_host {
-    name: "stats-log-api-gen-test",
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-g",
-        "-DUNIT_TEST",
-    ],
-    srcs: [
-        "Collation.cpp",
-        "test_collation.cpp",
-        "test.proto",
-    ],
-
-    static_libs: [
-        "libgmock_host",
-    ],
-
-    shared_libs: [
-        "libstats_proto_host",
-        "libprotobuf-cpp-full",
-    ],
-
-    proto: {
-        type: "full",
-        include_dirs: [
-            "external/protobuf/src",
-        ],
-    },
-}
-
-// ==========================================================
-// Native library
-// ==========================================================
-genrule {
-    name: "statslog.h",
-    tools: ["stats-log-api-gen"],
-    cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog.h",
-    out: [
-        "statslog.h",
-    ],
-}
-
-genrule {
-    name: "statslog.cpp",
-    tools: ["stats-log-api-gen"],
-    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog.cpp",
-    out: [
-        "statslog.cpp",
-    ],
-}
-
-cc_library {
-    name: "libstatslog",
-    host_supported: true,
-    generated_sources: [
-        "statslog.cpp",
-    ],
-    generated_headers: [
-        "statslog.h"
-    ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-    export_generated_headers: [
-        "statslog.h"
-    ],
-    shared_libs: [
-        "liblog",
-        "libcutils",
-    ],
-    target: {
-        android: {
-            shared_libs: [
-                "libstatssocket",
-                "libstatspull",
-            ],
-            export_shared_lib_headers: [
-                 "libstatssocket",
-                 "libstatspull",
-            ],
-        },
-        host: {
-            static_libs: [
-                "libstatssocket",
-                "libstatspull",
-                "statsd-aidl-ndk_platform",
-            ],
-            shared_libs: ["libbinder_ndk"],
-            export_static_lib_headers: [
-                "libstatssocket",
-                "libstatspull",
-            ],
-        },
-        darwin: {
-            enabled: false,
-        },
-    },
-}
-
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
deleted file mode 100644
index 56f4db0..0000000
--- a/tools/stats_log_api_gen/Collation.cpp
+++ /dev/null
@@ -1,601 +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 "Collation.h"
-
-#include <stdio.h>
-
-#include <map>
-
-#include "frameworks/proto_logging/stats/atoms.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using google::protobuf::OneofDescriptor;
-using google::protobuf::EnumDescriptor;
-using google::protobuf::FieldDescriptor;
-using google::protobuf::FileDescriptor;
-using google::protobuf::SourceLocation;
-using std::make_shared;
-using std::map;
-
-const bool dbg = false;
-
-//
-// AtomDecl class
-//
-
-AtomDecl::AtomDecl() : code(0), name() {
-}
-
-AtomDecl::AtomDecl(const AtomDecl& that)
-    : code(that.code),
-      name(that.name),
-      message(that.message),
-      fields(that.fields),
-      fieldNumberToAnnotations(that.fieldNumberToAnnotations),
-      primaryFields(that.primaryFields),
-      exclusiveField(that.exclusiveField),
-      defaultState(that.defaultState),
-      triggerStateReset(that.triggerStateReset),
-      nested(that.nested),
-      uidField(that.uidField) {
-}
-
-AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) {
-}
-
-AtomDecl::~AtomDecl() {
-}
-
-/**
- * Print an error message for a FieldDescriptor, including the file name and
- * line number.
- */
-static void print_error(const FieldDescriptor* field, const char* format, ...) {
-    const Descriptor* message = field->containing_type();
-    const FileDescriptor* file = message->file();
-
-    SourceLocation loc;
-    if (field->GetSourceLocation(&loc)) {
-        // TODO(b/162454173): this will work if we can figure out how to pass
-        // --include_source_info to protoc
-        fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
-    } else {
-        fprintf(stderr, "%s: ", file->name().c_str());
-    }
-    va_list args;
-    va_start(args, format);
-    vfprintf(stderr, format, args);
-    va_end(args);
-}
-
-/**
- * Convert a protobuf type into a java type.
- */
-static java_type_t java_type(const FieldDescriptor* field) {
-    int protoType = field->type();
-    switch (protoType) {
-        case FieldDescriptor::TYPE_DOUBLE:
-            return JAVA_TYPE_DOUBLE;
-        case FieldDescriptor::TYPE_FLOAT:
-            return JAVA_TYPE_FLOAT;
-        case FieldDescriptor::TYPE_INT64:
-            return JAVA_TYPE_LONG;
-        case FieldDescriptor::TYPE_UINT64:
-            return JAVA_TYPE_LONG;
-        case FieldDescriptor::TYPE_INT32:
-            return JAVA_TYPE_INT;
-        case FieldDescriptor::TYPE_FIXED64:
-            return JAVA_TYPE_LONG;
-        case FieldDescriptor::TYPE_FIXED32:
-            return JAVA_TYPE_INT;
-        case FieldDescriptor::TYPE_BOOL:
-            return JAVA_TYPE_BOOLEAN;
-        case FieldDescriptor::TYPE_STRING:
-            return JAVA_TYPE_STRING;
-        case FieldDescriptor::TYPE_GROUP:
-            return JAVA_TYPE_UNKNOWN;
-        case FieldDescriptor::TYPE_MESSAGE:
-            if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") {
-                return JAVA_TYPE_ATTRIBUTION_CHAIN;
-            } else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") {
-                return JAVA_TYPE_KEY_VALUE_PAIR;
-            } else if (field->options().GetExtension(os::statsd::log_mode) ==
-                       os::statsd::LogMode::MODE_BYTES) {
-                return JAVA_TYPE_BYTE_ARRAY;
-            } else {
-                return JAVA_TYPE_OBJECT;
-            }
-        case FieldDescriptor::TYPE_BYTES:
-            return JAVA_TYPE_BYTE_ARRAY;
-        case FieldDescriptor::TYPE_UINT32:
-            return JAVA_TYPE_INT;
-        case FieldDescriptor::TYPE_ENUM:
-            return JAVA_TYPE_ENUM;
-        case FieldDescriptor::TYPE_SFIXED32:
-            return JAVA_TYPE_INT;
-        case FieldDescriptor::TYPE_SFIXED64:
-            return JAVA_TYPE_LONG;
-        case FieldDescriptor::TYPE_SINT32:
-            return JAVA_TYPE_INT;
-        case FieldDescriptor::TYPE_SINT64:
-            return JAVA_TYPE_LONG;
-        default:
-            return JAVA_TYPE_UNKNOWN;
-    }
-}
-
-/**
- * Gather the enums info.
- */
-void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
-    for (int i = 0; i < enumDescriptor.value_count(); i++) {
-        atomField->enumValues[enumDescriptor.value(i)->number()] =
-                enumDescriptor.value(i)->name();
-    }
-}
-
-static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
-                                    const AnnotationId annotationId,
-                                    const AnnotationType annotationType,
-                                    const AnnotationValue annotationValue) {
-    if (dbg) {
-        printf("   Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
-               fieldNumber, annotationId, annotationType);
-    }
-    atomDecl->fieldNumberToAnnotations[fieldNumber].insert(
-            make_shared<Annotation>(annotationId, atomDecl->code, annotationType, annotationValue));
-}
-
-static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field,
-                                     const int fieldNumber, const java_type_t& javaType) {
-    int errorCount = 0;
-
-    if (field->options().HasExtension(os::statsd::state_field_option)) {
-        const os::statsd::StateAtomFieldOption& stateFieldOption =
-                field->options().GetExtension(os::statsd::state_field_option);
-        const bool primaryField = stateFieldOption.primary_field();
-        const bool exclusiveState = stateFieldOption.exclusive_state();
-        const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
-
-        // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
-        if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
-            print_error(field,
-                        "Field can be max 1 of primary_field, exclusive_state, "
-                        "or primary_field_first_uid: '%s'\n",
-                        atomDecl->message.c_str());
-            errorCount++;
-        }
-
-        if (primaryField) {
-            if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
-                javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
-                print_error(field, "Invalid primary state field: '%s'\n",
-                            atomDecl->message.c_str());
-                errorCount++;
-            } else {
-                atomDecl->primaryFields.push_back(fieldNumber);
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
-                                        ANNOTATION_TYPE_BOOL, AnnotationValue(true));
-            }
-        }
-
-        if (primaryFieldFirstUid) {
-            if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                print_error(field,
-                            "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
-                            "'%s'\n",
-                            atomDecl->message.c_str());
-                errorCount++;
-            } else {
-                atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
-                addAnnotationToAtomDecl(atomDecl, fieldNumber,
-                                        ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
-                                        AnnotationValue(true));
-            }
-        }
-
-        if (exclusiveState) {
-            if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
-                javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
-                print_error(field, "Invalid exclusive state field: '%s'\n",
-                            atomDecl->message.c_str());
-                errorCount++;
-            }
-
-            if (atomDecl->exclusiveField != 0) {
-                print_error(field,
-                            "Cannot have more than one exclusive state field in an "
-                            "atom: '%s'\n",
-                            atomDecl->message.c_str());
-                errorCount++;
-            } else {
-                atomDecl->exclusiveField = fieldNumber;
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
-                                        ANNOTATION_TYPE_BOOL, AnnotationValue(true));
-            }
-
-            if (stateFieldOption.has_default_state_value()) {
-                const int defaultState = stateFieldOption.default_state_value();
-                atomDecl->defaultState = defaultState;
-
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
-                                        ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
-            }
-
-            if (stateFieldOption.has_trigger_state_reset_value()) {
-                const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
-
-                atomDecl->triggerStateReset = triggerStateReset;
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
-                                        ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
-            }
-
-            if (stateFieldOption.has_nested()) {
-                const bool nested = stateFieldOption.nested();
-                atomDecl->nested = nested;
-
-                addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
-                                        ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
-            }
-        }
-    }
-
-    if (field->options().GetExtension(os::statsd::is_uid) == true) {
-        if (javaType != JAVA_TYPE_INT) {
-            print_error(field, "is_uid annotation can only be applied to int32 fields: '%s'\n",
-                        atomDecl->message.c_str());
-            errorCount++;
-        }
-
-        if (atomDecl->uidField == 0) {
-            atomDecl->uidField = fieldNumber;
-
-            addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID,
-                                    ANNOTATION_TYPE_BOOL, AnnotationValue(true));
-        } else {
-            print_error(field,
-                        "Cannot have more than one field in an atom with is_uid "
-                        "annotation: '%s'\n",
-                        atomDecl->message.c_str());
-            errorCount++;
-        }
-    }
-
-    return errorCount;
-}
-
-/**
- * Gather the info about an atom proto.
- */
-int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature) {
-    int errorCount = 0;
-
-    // Build a sorted list of the fields. Descriptor has them in source file
-    // order.
-    map<int, const FieldDescriptor*> fields;
-    for (int j = 0; j < atom->field_count(); j++) {
-        const FieldDescriptor* field = atom->field(j);
-        fields[field->number()] = field;
-    }
-
-    // Check that the parameters start at 1 and go up sequentially.
-    int expectedNumber = 1;
-    for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
-         it++) {
-        const int number = it->first;
-        const FieldDescriptor* field = it->second;
-        if (number != expectedNumber) {
-            print_error(field,
-                        "Fields must be numbered consecutively starting at 1:"
-                        " '%s' is %d but should be %d\n",
-                        field->name().c_str(), number, expectedNumber);
-            errorCount++;
-            expectedNumber = number;
-            continue;
-        }
-        expectedNumber++;
-    }
-
-    // Check that only allowed types are present. Remove any invalid ones.
-    for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
-         it++) {
-        const FieldDescriptor* field = it->second;
-        bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
-                             os::statsd::LogMode::MODE_BYTES;
-
-        java_type_t javaType = java_type(field);
-
-        if (javaType == JAVA_TYPE_UNKNOWN) {
-            print_error(field, "Unknown type for field: %s\n", field->name().c_str());
-            errorCount++;
-            continue;
-        } else if (javaType == JAVA_TYPE_OBJECT && atomDecl->code < PULL_ATOM_START_ID) {
-            // Allow attribution chain, but only at position 1.
-            print_error(field, "Message type not allowed for field in pushed atoms: %s\n",
-                        field->name().c_str());
-            errorCount++;
-            continue;
-        } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
-            print_error(field, "Raw bytes type not allowed for field: %s\n", field->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
-            print_error(field, "Cannot mark field %s as bytes.\n", field->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        // Doubles are not supported yet.
-        if (javaType == JAVA_TYPE_DOUBLE) {
-            print_error(field,
-                        "Doubles are not supported in atoms. Please change field %s "
-                        "to float\n",
-                        field->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        if (field->is_repeated() &&
-            !(javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || javaType == JAVA_TYPE_KEY_VALUE_PAIR)) {
-            print_error(field,
-                        "Repeated fields are not supported in atoms. Please make "
-                        "field %s not "
-                        "repeated.\n",
-                        field->name().c_str());
-            errorCount++;
-            continue;
-        }
-    }
-
-    // Check that if there's an attribution chain, it's at position 1.
-    for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
-         it++) {
-        int number = it->first;
-        if (number != 1) {
-            const FieldDescriptor* field = it->second;
-            java_type_t javaType = java_type(field);
-            if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                print_error(field,
-                            "AttributionChain fields must have field id 1, in message: '%s'\n",
-                            atom->name().c_str());
-                errorCount++;
-            }
-        }
-    }
-
-    // Build the type signature and the atom data.
-    for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
-         it++) {
-        const FieldDescriptor* field = it->second;
-        java_type_t javaType = java_type(field);
-        bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
-                             os::statsd::LogMode::MODE_BYTES;
-
-        AtomField atField(field->name(), javaType);
-
-        if (javaType == JAVA_TYPE_ENUM) {
-            // All enums are treated as ints when it comes to function signatures.
-            collate_enums(*field->enum_type(), &atField);
-        }
-
-        // Generate signature for atom.
-        if (javaType == JAVA_TYPE_ENUM) {
-            // All enums are treated as ints when it comes to function signatures.
-            signature->push_back(JAVA_TYPE_INT);
-        } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
-            signature->push_back(JAVA_TYPE_BYTE_ARRAY);
-        } else {
-            signature->push_back(javaType);
-        }
-
-        atomDecl->fields.push_back(atField);
-
-        errorCount += collate_field_annotations(atomDecl, field, it->first, javaType);
-    }
-
-    return errorCount;
-}
-
-// This function flattens the fields of the AttributionNode proto in an Atom
-// proto and generates the corresponding atom decl and signature.
-bool get_non_chained_node(const Descriptor* atom, AtomDecl* atomDecl,
-                          vector<java_type_t>* signature) {
-    // Build a sorted list of the fields. Descriptor has them in source file
-    // order.
-    map<int, const FieldDescriptor*> fields;
-    for (int j = 0; j < atom->field_count(); j++) {
-        const FieldDescriptor* field = atom->field(j);
-        fields[field->number()] = field;
-    }
-
-    AtomDecl attributionDecl;
-    vector<java_type_t> attributionSignature;
-    collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
-                 &attributionSignature);
-
-    // Build the type signature and the atom data.
-    bool has_attribution_node = false;
-    for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
-         it++) {
-        const FieldDescriptor* field = it->second;
-        java_type_t javaType = java_type(field);
-        if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            atomDecl->fields.insert(atomDecl->fields.end(), attributionDecl.fields.begin(),
-                                    attributionDecl.fields.end());
-            signature->insert(signature->end(), attributionSignature.begin(),
-                              attributionSignature.end());
-            has_attribution_node = true;
-
-        } else {
-            AtomField atField(field->name(), javaType);
-            if (javaType == JAVA_TYPE_ENUM) {
-                // All enums are treated as ints when it comes to function signatures.
-                signature->push_back(JAVA_TYPE_INT);
-                collate_enums(*field->enum_type(), &atField);
-            } else {
-                signature->push_back(javaType);
-            }
-            atomDecl->fields.push_back(atField);
-        }
-    }
-    return has_attribution_node;
-}
-
-static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl,
-                                             FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) {
-    for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin();
-         it != atomDecl->fieldNumberToAnnotations.end(); it++) {
-        const int fieldNumber = it->first;
-        (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl);
-    }
-}
-
-/**
- * Gather the info about the atoms.
- */
-int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms) {
-    int errorCount = 0;
-
-    for (int i = 0; i < descriptor->field_count(); i++) {
-        const FieldDescriptor* atomField = descriptor->field(i);
-
-        if (moduleName != DEFAULT_MODULE_NAME) {
-            const int moduleCount = atomField->options().ExtensionSize(os::statsd::module);
-            int j;
-            for (j = 0; j < moduleCount; ++j) {
-                const string atomModuleName =
-                        atomField->options().GetExtension(os::statsd::module, j);
-                if (atomModuleName == moduleName) {
-                    break;
-                }
-            }
-
-            // This atom is not in the module we're interested in; skip it.
-            if (moduleCount == j) {
-                if (dbg) {
-                    printf("   Skipping %s (%d)\n", atomField->name().c_str(), atomField->number());
-                }
-                continue;
-            }
-        }
-
-        if (dbg) {
-            printf("   %s (%d)\n", atomField->name().c_str(), atomField->number());
-        }
-
-        // StatsEvent only has one oneof, which contains only messages. Don't allow
-        // other types.
-        if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) {
-            print_error(atomField,
-                        "Bad type for atom. StatsEvent can only have message type "
-                        "fields: %s\n",
-                        atomField->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        const Descriptor* atom = atomField->message_type();
-        shared_ptr<AtomDecl> atomDecl =
-                make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
-
-        if (atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
-            addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
-                                    ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL,
-                                    AnnotationValue(true));
-            if (dbg) {
-                printf("%s can have timestamp truncated\n", atomField->name().c_str());
-            }
-        }
-
-        vector<java_type_t> signature;
-        errorCount += collate_atom(atom, atomDecl.get(), &signature);
-        if (!atomDecl->primaryFields.empty() && atomDecl->exclusiveField == 0) {
-            print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
-                        atomField->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        const OneofDescriptor* oneofAtom = atomField->containing_oneof();
-        if (oneofAtom == nullptr) {
-            print_error(atomField, "Atom is not declared in a `oneof` field: %s\n",
-                        atomField->name().c_str());
-            errorCount++;
-            continue;
-        } else if ((oneofAtom->name() != ONEOF_PUSHED_ATOM_NAME) &&
-                 (oneofAtom->name() != ONEOF_PULLED_ATOM_NAME)) {
-            print_error(atomField, "Atom is neither a pushed nor pulled atom: %s\n",
-                        atomField->name().c_str());
-            errorCount++;
-            continue;
-        }
-
-        FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = oneofAtom->name() ==
-            ONEOF_PUSHED_ATOM_NAME ? atoms->signatureInfoMap[signature] :
-            atoms->pulledAtomsSignatureInfoMap[signature];
-        populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet);
-
-        atoms->decls.insert(atomDecl);
-
-        shared_ptr<AtomDecl> nonChainedAtomDecl =
-                make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
-        vector<java_type_t> nonChainedSignature;
-        if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) {
-            FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet =
-                    atoms->nonChainedSignatureInfoMap[nonChainedSignature];
-            populateFieldNumberToAtomDeclSet(nonChainedAtomDecl,
-                                             &nonChainedFieldNumberToAtomDeclSet);
-
-            atoms->non_chained_decls.insert(nonChainedAtomDecl);
-        }
-    }
-
-    if (dbg) {
-        // Signatures for pushed atoms.
-        printf("signatures = [\n");
-        for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin();
-             it != atoms->signatureInfoMap.end(); it++) {
-            printf("   ");
-            for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
-                 jt++) {
-                printf(" %d", static_cast<int>(*jt));
-            }
-            printf("\n");
-        }
-
-        // Signatures for pull atoms.
-        for (SignatureInfoMap::const_iterator it = atoms->pulledAtomsSignatureInfoMap.begin();
-             it != atoms->pulledAtomsSignatureInfoMap.end(); it++) {
-            printf("   ");
-            for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
-                 jt++) {
-                printf(" %d", static_cast<int>(*jt));
-            }
-            printf("\n");
-        }
-        printf("]\n");
-    }
-
-    return errorCount;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
deleted file mode 100644
index b13851c..0000000
--- a/tools/stats_log_api_gen/Collation.h
+++ /dev/null
@@ -1,211 +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 ANDROID_STATS_LOG_API_GEN_COLLATION_H
-#define ANDROID_STATS_LOG_API_GEN_COLLATION_H
-
-#include <google/protobuf/descriptor.h>
-#include <stdint.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "frameworks/proto_logging/stats/atom_field_options.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using google::protobuf::OneofDescriptor;
-using google::protobuf::Descriptor;
-using google::protobuf::FieldDescriptor;
-using std::map;
-using std::set;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-
-const int PULL_ATOM_START_ID = 10000;
-
-const int FIRST_UID_IN_CHAIN_ID = 0;
-
-/**
- * The types of oneof atoms.
- *
- * `OneofDescriptor::name()` returns the name of the oneof.
- */
-const char ONEOF_PUSHED_ATOM_NAME[] = "pushed";
-const char ONEOF_PULLED_ATOM_NAME[] = "pulled";
-
-enum AnnotationId : uint8_t {
-    ANNOTATION_ID_IS_UID = 1,
-    ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2,
-    ANNOTATION_ID_PRIMARY_FIELD = 3,
-    ANNOTATION_ID_EXCLUSIVE_STATE = 4,
-    ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5,
-    ANNOTATION_ID_DEFAULT_STATE = 6,
-    ANNOTATION_ID_TRIGGER_STATE_RESET = 7,
-    ANNOTATION_ID_STATE_NESTED = 8,
-};
-
-const int ATOM_ID_FIELD_NUMBER = -1;
-
-const char DEFAULT_MODULE_NAME[] = "DEFAULT";
-
-/**
- * The types for atom parameters.
- */
-typedef enum {
-    JAVA_TYPE_UNKNOWN = 0,
-
-    JAVA_TYPE_ATTRIBUTION_CHAIN = 1,
-    JAVA_TYPE_BOOLEAN = 2,
-    JAVA_TYPE_INT = 3,
-    JAVA_TYPE_LONG = 4,
-    JAVA_TYPE_FLOAT = 5,
-    JAVA_TYPE_DOUBLE = 6,
-    JAVA_TYPE_STRING = 7,
-    JAVA_TYPE_ENUM = 8,
-    JAVA_TYPE_KEY_VALUE_PAIR = 9,
-
-    JAVA_TYPE_OBJECT = -1,
-    JAVA_TYPE_BYTE_ARRAY = -2,
-} java_type_t;
-
-enum AnnotationType {
-    ANNOTATION_TYPE_UNKNOWN = 0,
-    ANNOTATION_TYPE_INT = 1,
-    ANNOTATION_TYPE_BOOL = 2,
-};
-
-union AnnotationValue {
-    int intValue;
-    bool boolValue;
-
-    explicit AnnotationValue(const int value) : intValue(value) {
-    }
-    explicit AnnotationValue(const bool value) : boolValue(value) {
-    }
-};
-
-struct Annotation {
-    const AnnotationId annotationId;
-    const int atomId;
-    AnnotationType type;
-    AnnotationValue value;
-
-    inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type,
-                      AnnotationValue value)
-        : annotationId(annotationId), atomId(atomId), type(type), value(value) {
-    }
-    inline ~Annotation() {
-    }
-
-    inline bool operator<(const Annotation& that) const {
-        return atomId == that.atomId ? annotationId < that.annotationId : atomId < that.atomId;
-    }
-};
-
-struct SharedComparator {
-    template <typename T>
-    inline bool operator()(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs) const {
-        return (*lhs) < (*rhs);
-    }
-};
-
-using AnnotationSet = set<shared_ptr<Annotation>, SharedComparator>;
-
-using FieldNumberToAnnotations = map<int, AnnotationSet>;
-
-/**
- * The name and type for an atom field.
- */
-struct AtomField {
-    string name;
-    java_type_t javaType;
-
-    // If the field is of type enum, the following map contains the list of enum
-    // values.
-    map<int /* numeric value */, string /* value name */> enumValues;
-
-    inline AtomField() : name(), javaType(JAVA_TYPE_UNKNOWN) {
-    }
-    inline AtomField(const AtomField& that)
-        : name(that.name), javaType(that.javaType), enumValues(that.enumValues) {
-    }
-
-    inline AtomField(string n, java_type_t jt) : name(n), javaType(jt) {
-    }
-    inline ~AtomField() {
-    }
-};
-
-/**
- * The name and code for an atom.
- */
-struct AtomDecl {
-    int code;
-    string name;
-
-    string message;
-    vector<AtomField> fields;
-
-    FieldNumberToAnnotations fieldNumberToAnnotations;
-
-    vector<int> primaryFields;
-    int exclusiveField = 0;
-    int defaultState = INT_MAX;
-    int triggerStateReset = INT_MAX;
-    bool nested = true;
-
-    int uidField = 0;
-
-    AtomDecl();
-    AtomDecl(const AtomDecl& that);
-    AtomDecl(int code, const string& name, const string& message);
-    ~AtomDecl();
-
-    inline bool operator<(const AtomDecl& that) const {
-        return (code == that.code) ? (name < that.name) : (code < that.code);
-    }
-};
-
-using AtomDeclSet = set<shared_ptr<AtomDecl>, SharedComparator>;
-
-// Maps a field number to a set of atoms that have annotation(s) for their field with that field
-// number.
-using FieldNumberToAtomDeclSet = map<int, AtomDeclSet>;
-
-using SignatureInfoMap = map<vector<java_type_t>, FieldNumberToAtomDeclSet>;
-
-struct Atoms {
-    SignatureInfoMap signatureInfoMap;
-    SignatureInfoMap pulledAtomsSignatureInfoMap;
-    AtomDeclSet decls;
-    AtomDeclSet non_chained_decls;
-    SignatureInfoMap nonChainedSignatureInfoMap;
-};
-
-/**
- * Gather the information about the atoms.  Returns the number of errors.
- */
-int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms);
-int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature);
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-#endif  // ANDROID_STATS_LOG_API_GEN_COLLATION_H
diff --git a/tools/stats_log_api_gen/OWNERS b/tools/stats_log_api_gen/OWNERS
deleted file mode 100644
index 41a0c95..0000000
--- a/tools/stats_log_api_gen/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-yro@google.com
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
deleted file mode 100644
index 6fcf267..0000000
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ /dev/null
@@ -1,384 +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.
- */
-
-#include "java_writer.h"
-
-#include "java_writer_q.h"
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-static int write_java_q_logger_class(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                                     const AtomDecl& attributionDecl) {
-    fprintf(out, "\n");
-    fprintf(out, "    // Write logging helper methods for statsd in Q and earlier.\n");
-    fprintf(out, "    private static class QLogger {\n");
-
-    write_java_q_logging_constants(out, "        ");
-
-    // Print Q write methods.
-    fprintf(out, "\n");
-    fprintf(out, "        // Write methods.\n");
-    write_java_methods_q_schema(out, signatureInfoMap, attributionDecl, "        ");
-
-    fprintf(out, "    }\n");
-    return 0;
-}
-
-static void write_java_annotation_constants(FILE* out) {
-    fprintf(out, "    // Annotation constants.\n");
-
-    const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
-    for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
-        fprintf(out, "    public static final byte %s = %hhu;\n", name.c_str(), id);
-    }
-    fprintf(out, "\n");
-}
-
-static void write_annotations(FILE* out, int argIndex,
-                              const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet) {
-    FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
-            fieldNumberToAtomDeclSet.find(argIndex);
-    if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
-        return;
-    }
-    const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
-    const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
-    for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
-        const string atomConstant = make_constant_name(atomDecl->name);
-        fprintf(out, "        if (%s == code) {\n", atomConstant.c_str());
-        const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
-        int resetState = -1;
-        int defaultState = -1;
-        for (const shared_ptr<Annotation>& annotation : annotations) {
-            const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
-            switch (annotation->type) {
-                case ANNOTATION_TYPE_INT:
-                    if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
-                        resetState = annotation->value.intValue;
-                    } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
-                        defaultState = annotation->value.intValue;
-                    } else {
-                        fprintf(out, "            builder.addIntAnnotation(%s, %d);\n",
-                                annotationConstant.c_str(), annotation->value.intValue);
-                    }
-                    break;
-                case ANNOTATION_TYPE_BOOL:
-                    fprintf(out, "            builder.addBooleanAnnotation(%s, %s);\n",
-                            annotationConstant.c_str(),
-                            annotation->value.boolValue ? "true" : "false");
-                    break;
-                default:
-                    break;
-            }
-        }
-        if (defaultState != -1 && resetState != -1) {
-            const string& annotationConstant =
-                    ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
-            fprintf(out, "            if (arg%d == %d) {\n", argIndex, resetState);
-            fprintf(out, "                builder.addIntAnnotation(%s, %d);\n",
-                    annotationConstant.c_str(), defaultState);
-            fprintf(out, "            }\n");
-        }
-        fprintf(out, "        }\n");
-    }
-}
-
-static void write_method_signature(FILE* out, const vector<java_type_t>& signature,
-                                   const AtomDecl& attributionDecl) {
-    int argIndex = 1;
-    for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-         arg++) {
-        if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            for (const auto& chainField : attributionDecl.fields) {
-                fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
-                        chainField.name.c_str());
-            }
-        } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out, ", android.util.SparseArray<Object> valueMap");
-        } else {
-            fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
-        }
-        argIndex++;
-    }
-}
-
-static int write_method_body(FILE* out, const vector<java_type_t>& signature,
-                             const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
-                             const AtomDecl& attributionDecl, const string& indent) {
-    // Start StatsEvent.Builder.
-    fprintf(out,
-            "%s        final StatsEvent.Builder builder = "
-            "StatsEvent.newBuilder();\n",
-            indent.c_str());
-
-    // Write atom code.
-    fprintf(out, "%s        builder.setAtomId(code);\n", indent.c_str());
-    write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet);
-
-    // Write the args.
-    int argIndex = 1;
-    for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-         arg++) {
-        switch (*arg) {
-            case JAVA_TYPE_BOOLEAN:
-                fprintf(out, "%s        builder.writeBoolean(arg%d);\n", indent.c_str(),
-                        argIndex);
-                break;
-            case JAVA_TYPE_INT:
-            case JAVA_TYPE_ENUM:
-                fprintf(out, "%s        builder.writeInt(arg%d);\n", indent.c_str(), argIndex);
-                break;
-            case JAVA_TYPE_FLOAT:
-                fprintf(out, "%s        builder.writeFloat(arg%d);\n", indent.c_str(),
-                        argIndex);
-                break;
-            case JAVA_TYPE_LONG:
-                fprintf(out, "%s        builder.writeLong(arg%d);\n", indent.c_str(), argIndex);
-                break;
-            case JAVA_TYPE_STRING:
-                fprintf(out, "%s        builder.writeString(arg%d);\n", indent.c_str(),
-                        argIndex);
-                break;
-            case JAVA_TYPE_BYTE_ARRAY:
-                fprintf(out,
-                        "%s        builder.writeByteArray(null == arg%d ? new byte[0] : "
-                        "arg%d);\n",
-                        indent.c_str(), argIndex, argIndex);
-                break;
-            case JAVA_TYPE_ATTRIBUTION_CHAIN: {
-                const char* uidName = attributionDecl.fields.front().name.c_str();
-                const char* tagName = attributionDecl.fields.back().name.c_str();
-
-                fprintf(out, "%s        builder.writeAttributionChain(\n", indent.c_str());
-                fprintf(out, "%s                null == %s ? new int[0] : %s,\n",
-                        indent.c_str(), uidName, uidName);
-                fprintf(out, "%s                null == %s ? new String[0] : %s);\n",
-                        indent.c_str(), tagName, tagName);
-                break;
-            }
-            case JAVA_TYPE_KEY_VALUE_PAIR:
-                fprintf(out, "\n");
-                fprintf(out, "%s        // Write KeyValuePairs.\n", indent.c_str());
-                fprintf(out, "%s        final int count = valueMap.size();\n", indent.c_str());
-                fprintf(out, "%s        android.util.SparseIntArray intMap = null;\n",
-                        indent.c_str());
-                fprintf(out, "%s        android.util.SparseLongArray longMap = null;\n",
-                        indent.c_str());
-                fprintf(out, "%s        android.util.SparseArray<String> stringMap = null;\n",
-                        indent.c_str());
-                fprintf(out, "%s        android.util.SparseArray<Float> floatMap = null;\n",
-                        indent.c_str());
-                fprintf(out, "%s        for (int i = 0; i < count; i++) {\n", indent.c_str());
-                fprintf(out, "%s            final int key = valueMap.keyAt(i);\n",
-                        indent.c_str());
-                fprintf(out, "%s            final Object value = valueMap.valueAt(i);\n",
-                        indent.c_str());
-                fprintf(out, "%s            if (value instanceof Integer) {\n", indent.c_str());
-                fprintf(out, "%s                if (null == intMap) {\n", indent.c_str());
-                fprintf(out,
-                        "%s                    intMap = new "
-                        "android.util.SparseIntArray();\n",
-                        indent.c_str());
-                fprintf(out, "%s                }\n", indent.c_str());
-                fprintf(out, "%s                intMap.put(key, (Integer) value);\n",
-                        indent.c_str());
-                fprintf(out, "%s            } else if (value instanceof Long) {\n",
-                        indent.c_str());
-                fprintf(out, "%s                if (null == longMap) {\n", indent.c_str());
-                fprintf(out,
-                        "%s                    longMap = new "
-                        "android.util.SparseLongArray();\n",
-                        indent.c_str());
-                fprintf(out, "%s                }\n", indent.c_str());
-                fprintf(out, "%s                longMap.put(key, (Long) value);\n",
-                        indent.c_str());
-                fprintf(out, "%s            } else if (value instanceof String) {\n",
-                        indent.c_str());
-                fprintf(out, "%s                if (null == stringMap) {\n", indent.c_str());
-                fprintf(out,
-                        "%s                    stringMap = new "
-                        "android.util.SparseArray<>();\n",
-                        indent.c_str());
-                fprintf(out, "%s                }\n", indent.c_str());
-                fprintf(out, "%s                stringMap.put(key, (String) value);\n",
-                        indent.c_str());
-                fprintf(out, "%s            } else if (value instanceof Float) {\n",
-                        indent.c_str());
-                fprintf(out, "%s                if (null == floatMap) {\n", indent.c_str());
-                fprintf(out,
-                        "%s                    floatMap = new "
-                        "android.util.SparseArray<>();\n",
-                        indent.c_str());
-                fprintf(out, "%s                }\n", indent.c_str());
-                fprintf(out, "%s                floatMap.put(key, (Float) value);\n",
-                        indent.c_str());
-                fprintf(out, "%s            }\n", indent.c_str());
-                fprintf(out, "%s        }\n", indent.c_str());
-                fprintf(out,
-                        "%s        builder.writeKeyValuePairs("
-                        "intMap, longMap, stringMap, floatMap);\n",
-                        indent.c_str());
-                break;
-            default:
-                // Unsupported types: OBJECT, DOUBLE.
-                fprintf(stderr, "Encountered unsupported type.");
-                return 1;
-        }
-        write_annotations(out, argIndex, fieldNumberToAtomDeclSet);
-        argIndex++;
-    }
-    return 0;
-}
-
-static int write_java_pushed_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                              const AtomDecl& attributionDecl, const bool supportQ) {
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        // Print method signature.
-        fprintf(out, "    public static void write(int code");
-        const vector<java_type_t>& signature = signatureInfoMapIt->first;
-        const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
-        write_method_signature(out, signature, attributionDecl);
-        fprintf(out, ") {\n");
-
-        // Print method body.
-        string indent("");
-        if (supportQ) {
-            fprintf(out, "        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
-            indent = "    ";
-        }
-
-        int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
-                                    attributionDecl, indent);
-        if (ret != 0) {
-            return ret;
-        }
-        fprintf(out, "\n");
-
-        fprintf(out, "%s        builder.usePooledBuffer();\n", indent.c_str());
-        fprintf(out, "%s        StatsLog.write(builder.build());\n", indent.c_str());
-
-        // Add support for writing using Q schema if this is not the default module.
-        if (supportQ) {
-            fprintf(out, "        } else {\n");
-            fprintf(out, "            QLogger.write(code");
-            int argIndex = 1;
-            for (vector<java_type_t>::const_iterator arg = signature.begin();
-                 arg != signature.end(); arg++) {
-                if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                    const char* uidName = attributionDecl.fields.front().name.c_str();
-                    const char* tagName = attributionDecl.fields.back().name.c_str();
-                    fprintf(out, ", %s, %s", uidName, tagName);
-                } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                    // Module logging does not yet support key value pair.
-                    fprintf(stderr, "Module logging does not yet support key value pair.\n");
-                    return 1;
-                } else {
-                    fprintf(out, ", arg%d", argIndex);
-                }
-                argIndex++;
-            }
-            fprintf(out, ");\n");
-            fprintf(out, "        }\n");  // if
-        }
-
-        fprintf(out, "    }\n");  // method
-        fprintf(out, "\n");
-    }
-    return 0;
-}
-
-static int write_java_pulled_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                              const AtomDecl& attributionDecl) {
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        // Print method signature.
-        fprintf(out, "    public static StatsEvent buildStatsEvent(int code");
-        const vector<java_type_t>& signature = signatureInfoMapIt->first;
-        const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
-        write_method_signature(out, signature, attributionDecl);
-        fprintf(out, ") {\n");
-
-        // Print method body.
-        string indent("");
-        int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
-                                    attributionDecl, indent);
-        if (ret != 0) {
-            return ret;
-        }
-        fprintf(out, "\n");
-
-        fprintf(out, "%s        return builder.build();\n", indent.c_str());
-
-        fprintf(out, "    }\n");  // method
-        fprintf(out, "\n");
-    }
-    return 0;
-}
-
-int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                         const string& javaClass, const string& javaPackage, const bool supportQ,
-                         const bool supportWorkSource) {
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-    fprintf(out, "package %s;\n", javaPackage.c_str());
-    fprintf(out, "\n");
-    fprintf(out, "\n");
-    if (supportQ) {
-        fprintf(out, "import android.os.Build;\n");
-        fprintf(out, "import android.os.SystemClock;\n");
-    }
-
-    fprintf(out, "import android.util.StatsEvent;\n");
-    fprintf(out, "import android.util.StatsLog;\n");
-
-    fprintf(out, "\n");
-    fprintf(out, "\n");
-    fprintf(out, "/**\n");
-    fprintf(out, " * Utility class for logging statistics events.\n");
-    fprintf(out, " */\n");
-    fprintf(out, "public class %s {\n", javaClass.c_str());
-
-    write_java_atom_codes(out, atoms);
-    write_java_enum_values(out, atoms);
-    write_java_annotation_constants(out);
-
-    int errors = 0;
-
-    // Print write methods.
-    fprintf(out, "    // Write methods\n");
-    errors += write_java_pushed_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
-    errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap);
-    errors += write_java_pulled_methods(out, atoms.pulledAtomsSignatureInfoMap,
-                                                   attributionDecl);
-    if (supportWorkSource) {
-        errors += write_java_work_source_methods(out, atoms.signatureInfoMap);
-    }
-
-    if (supportQ) {
-        errors += write_java_q_logger_class(out, atoms.signatureInfoMap, attributionDecl);
-    }
-
-    fprintf(out, "}\n");
-
-    return errors;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
deleted file mode 100644
index afd992b..0000000
--- a/tools/stats_log_api_gen/java_writer.h
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
-#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                         const string& javaClass, const string& javaPackage, const bool supportQ,
-                         const bool supportWorkSource);
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-#endif  // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
deleted file mode 100644
index be7cb4a..0000000
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ /dev/null
@@ -1,601 +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.
- */
-
-#include "java_writer_q.h"
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-void write_java_q_logging_constants(FILE* out, const string& indent) {
-    fprintf(out, "%s// Payload limits.\n", indent.c_str());
-    fprintf(out, "%sprivate static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n", indent.c_str());
-    fprintf(out,
-            "%sprivate static final int MAX_EVENT_PAYLOAD = "
-            "LOGGER_ENTRY_MAX_PAYLOAD - 4;\n",
-            indent.c_str());
-
-    // Value types. Must match with EventLog.java and log.h.
-    fprintf(out, "\n");
-    fprintf(out, "%s// Value types.\n", indent.c_str());
-    fprintf(out, "%sprivate static final byte INT_TYPE = 0;\n", indent.c_str());
-    fprintf(out, "%sprivate static final byte LONG_TYPE = 1;\n", indent.c_str());
-    fprintf(out, "%sprivate static final byte STRING_TYPE = 2;\n", indent.c_str());
-    fprintf(out, "%sprivate static final byte LIST_TYPE = 3;\n", indent.c_str());
-    fprintf(out, "%sprivate static final byte FLOAT_TYPE = 4;\n", indent.c_str());
-
-    // Size of each value type.
-    // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for
-    // the value.
-    fprintf(out, "\n");
-    fprintf(out, "%s// Size of each value type.\n", indent.c_str());
-    fprintf(out, "%sprivate static final int INT_TYPE_SIZE = 5;\n", indent.c_str());
-    fprintf(out, "%sprivate static final int FLOAT_TYPE_SIZE = 5;\n", indent.c_str());
-    // Longs take 9 bytes, 1 for the type and 8 for the value.
-    fprintf(out, "%sprivate static final int LONG_TYPE_SIZE = 9;\n", indent.c_str());
-    // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the
-    // length.
-    fprintf(out, "%sprivate static final int STRING_TYPE_OVERHEAD = 5;\n", indent.c_str());
-    fprintf(out, "%sprivate static final int LIST_TYPE_OVERHEAD = 2;\n", indent.c_str());
-}
-
-int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                                const AtomDecl& attributionDecl, const string& indent) {
-    int requiredHelpers = 0;
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        // Print method signature.
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-        fprintf(out, "%spublic static void write(int code", indent.c_str());
-        int argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                for (const auto& chainField : attributionDecl.fields) {
-                    fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
-                            chainField.name.c_str());
-                }
-            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", android.util.SparseArray<Object> valueMap");
-            } else {
-                fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ") {\n");
-
-        // Calculate the size of the buffer.
-        fprintf(out, "%s    // Initial overhead of the list, timestamp, and atom tag.\n",
-                indent.c_str());
-        fprintf(out,
-                "%s    int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + "
-                "INT_TYPE_SIZE;\n",
-                indent.c_str());
-        argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            switch (*arg) {
-                case JAVA_TYPE_BOOLEAN:
-                case JAVA_TYPE_INT:
-                case JAVA_TYPE_FLOAT:
-                case JAVA_TYPE_ENUM:
-                    fprintf(out, "%s    needed += INT_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_LONG:
-                    // Longs take 9 bytes, 1 for the type and 8 for the value.
-                    fprintf(out, "%s    needed += LONG_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_STRING:
-                    // Strings take 5 metadata bytes + length of byte encoded string.
-                    fprintf(out, "%s    if (arg%d == null) {\n", indent.c_str(), argIndex);
-                    fprintf(out, "%s        arg%d = \"\";\n", indent.c_str(), argIndex);
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out,
-                            "%s    byte[] arg%dBytes = "
-                            "arg%d.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
-                            indent.c_str(), argIndex, argIndex);
-                    fprintf(out, "%s    needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
-                            indent.c_str(), argIndex);
-                    break;
-                case JAVA_TYPE_BYTE_ARRAY:
-                    // Byte arrays take 5 metadata bytes + length of byte array.
-                    fprintf(out, "%s    if (arg%d == null) {\n", indent.c_str(), argIndex);
-                    fprintf(out, "%s        arg%d = new byte[0];\n", indent.c_str(), argIndex);
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out, "%s    needed += STRING_TYPE_OVERHEAD + arg%d.length;\n",
-                            indent.c_str(), argIndex);
-                    break;
-                case JAVA_TYPE_ATTRIBUTION_CHAIN: {
-                    const char* uidName = attributionDecl.fields.front().name.c_str();
-                    const char* tagName = attributionDecl.fields.back().name.c_str();
-                    // Null checks on the params.
-                    fprintf(out, "%s    if (%s == null) {\n", indent.c_str(), uidName);
-                    fprintf(out, "%s        %s = new %s[0];\n", indent.c_str(), uidName,
-                            java_type_name(attributionDecl.fields.front().javaType));
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out, "%s    if (%s == null) {\n", indent.c_str(), tagName);
-                    fprintf(out, "%s        %s = new %s[0];\n", indent.c_str(), tagName,
-                            java_type_name(attributionDecl.fields.back().javaType));
-                    fprintf(out, "%s    }\n", indent.c_str());
-
-                    // First check that the lengths of the uid and tag arrays are the
-                    // same.
-                    fprintf(out, "%s    if (%s.length != %s.length) {\n", indent.c_str(), uidName,
-                            tagName);
-                    fprintf(out, "%s        return;\n", indent.c_str());
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out, "%s    int attrSize = LIST_TYPE_OVERHEAD;\n", indent.c_str());
-                    fprintf(out, "%s    for (int i = 0; i < %s.length; i++) {\n", indent.c_str(),
-                            tagName);
-                    fprintf(out, "%s        String str%d = (%s[i] == null) ? \"\" : %s[i];\n",
-                            indent.c_str(), argIndex, tagName, tagName);
-                    fprintf(out,
-                            "%s        int str%dlen = "
-                            "str%d.getBytes(java.nio.charset.StandardCharsets.UTF_8)."
-                            "length;\n",
-                            indent.c_str(), argIndex, argIndex);
-                    fprintf(out,
-                            "%s        attrSize += "
-                            "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + "
-                            "str%dlen;\n",
-                            indent.c_str(), argIndex);
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out, "%s    needed += attrSize;\n", indent.c_str());
-                    break;
-                }
-                case JAVA_TYPE_KEY_VALUE_PAIR: {
-                    fprintf(out, "%s    // Calculate bytes needed by Key Value Pairs.\n",
-                            indent.c_str());
-                    fprintf(out, "%s    final int count = valueMap.size();\n", indent.c_str());
-                    fprintf(out, "%s    android.util.SparseIntArray intMap = null;\n",
-                            indent.c_str());
-                    fprintf(out, "%s    android.util.SparseLongArray longMap = null;\n",
-                            indent.c_str());
-                    fprintf(out, "%s    android.util.SparseArray<String> stringMap = null;\n",
-                            indent.c_str());
-                    fprintf(out, "%s    android.util.SparseArray<Float> floatMap = null;\n",
-                            indent.c_str());
-                    fprintf(out, "%s    int keyValuePairSize = LIST_TYPE_OVERHEAD;\n",
-                            indent.c_str());
-                    fprintf(out, "%s    for (int i = 0; i < count; i++) {\n", indent.c_str());
-                    fprintf(out, "%s        final int key = valueMap.keyAt(i);\n", indent.c_str());
-                    fprintf(out, "%s        final Object value = valueMap.valueAt(i);\n",
-                            indent.c_str());
-                    fprintf(out, "%s        if (value instanceof Integer) {\n", indent.c_str());
-                    fprintf(out, "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
-                            indent.c_str());
-                    fprintf(out, "%s                    + INT_TYPE_SIZE + INT_TYPE_SIZE;\n",
-                            indent.c_str());
-                    fprintf(out, "%s            if (null == intMap) {\n", indent.c_str());
-                    fprintf(out, "%s                intMap = new android.util.SparseIntArray();\n",
-                            indent.c_str());
-                    fprintf(out, "%s            }\n", indent.c_str());
-                    fprintf(out, "%s            intMap.put(key, (Integer) value);\n",
-                            indent.c_str());
-                    fprintf(out, "%s        } else if (value instanceof Long) {\n", indent.c_str());
-                    fprintf(out, "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
-                            indent.c_str());
-                    fprintf(out, "%s                    + INT_TYPE_SIZE + LONG_TYPE_SIZE;\n",
-                            indent.c_str());
-                    fprintf(out, "%s            if (null == longMap) {\n", indent.c_str());
-                    fprintf(out,
-                            "%s                longMap = new "
-                            "android.util.SparseLongArray();\n",
-                            indent.c_str());
-                    fprintf(out, "%s            }\n", indent.c_str());
-                    fprintf(out, "%s            longMap.put(key, (Long) value);\n", indent.c_str());
-                    fprintf(out, "%s        } else if (value instanceof String) {\n",
-                            indent.c_str());
-                    fprintf(out,
-                            "%s            final String str = (value == null) ? \"\" : "
-                            "(String) value;\n",
-                            indent.c_str());
-                    fprintf(out,
-                            "%s            final int len = "
-                            "str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n",
-                            indent.c_str());
-                    fprintf(out,
-                            "%s            keyValuePairSize += LIST_TYPE_OVERHEAD + "
-                            "INT_TYPE_SIZE\n",
-                            indent.c_str());
-                    fprintf(out, "%s                    + STRING_TYPE_OVERHEAD + len;\n",
-                            indent.c_str());
-                    fprintf(out, "%s            if (null == stringMap) {\n", indent.c_str());
-                    fprintf(out,
-                            "%s                stringMap = new "
-                            "android.util.SparseArray<>();\n",
-                            indent.c_str());
-                    fprintf(out, "%s            }\n", indent.c_str());
-                    fprintf(out, "%s            stringMap.put(key, str);\n", indent.c_str());
-                    fprintf(out, "%s        } else if (value instanceof Float) {\n",
-                            indent.c_str());
-                    fprintf(out, "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
-                            indent.c_str());
-                    fprintf(out, "%s                    + INT_TYPE_SIZE + FLOAT_TYPE_SIZE;\n",
-                            indent.c_str());
-                    fprintf(out, "%s            if (null == floatMap) {\n", indent.c_str());
-                    fprintf(out,
-                            "%s                floatMap = new "
-                            "android.util.SparseArray<>();\n",
-                            indent.c_str());
-                    fprintf(out, "%s            }\n", indent.c_str());
-                    fprintf(out, "%s            floatMap.put(key, (Float) value);\n",
-                            indent.c_str());
-                    fprintf(out, "%s        }\n", indent.c_str());
-                    fprintf(out, "%s    }\n", indent.c_str());
-                    fprintf(out, "%s    needed += keyValuePairSize;\n", indent.c_str());
-                    break;
-                }
-                default:
-                    // Unsupported types: OBJECT, DOUBLE.
-                    fprintf(stderr, "Module logging does not yet support Object and Double.\n");
-                    return 1;
-            }
-            argIndex++;
-        }
-
-        // Now we have the size that is needed. Check for overflow and return if
-        // needed.
-        fprintf(out, "%s    if (needed > MAX_EVENT_PAYLOAD) {\n", indent.c_str());
-        fprintf(out, "%s        return;\n", indent.c_str());
-        fprintf(out, "%s    }\n", indent.c_str());
-
-        // Create new buffer, and associated data types.
-        fprintf(out, "%s    byte[] buff = new byte[needed];\n", indent.c_str());
-        fprintf(out, "%s    int pos = 0;\n", indent.c_str());
-
-        // Initialize the buffer with list data type.
-        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s    buff[pos + 1] = %zu;\n", indent.c_str(), signature.size() + 2);
-        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
-        // Write timestamp.
-        fprintf(out, "%s    long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n",
-                indent.c_str());
-        fprintf(out, "%s    buff[pos] = LONG_TYPE;\n", indent.c_str());
-        fprintf(out, "%s    copyLong(buff, pos + 1, elapsedRealtime);\n", indent.c_str());
-        fprintf(out, "%s    pos += LONG_TYPE_SIZE;\n", indent.c_str());
-
-        // Write atom code.
-        fprintf(out, "%s    buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s    copyInt(buff, pos + 1, code);\n", indent.c_str());
-        fprintf(out, "%s    pos += INT_TYPE_SIZE;\n", indent.c_str());
-
-        // Write the args.
-        argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            switch (*arg) {
-                case JAVA_TYPE_BOOLEAN:
-                    fprintf(out, "%s    buff[pos] = INT_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyInt(buff, pos + 1, arg%d? 1 : 0);\n", indent.c_str(),
-                            argIndex);
-                    fprintf(out, "%s    pos += INT_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_INT:
-                case JAVA_TYPE_ENUM:
-                    fprintf(out, "%s    buff[pos] = INT_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyInt(buff, pos + 1, arg%d);\n", indent.c_str(),
-                            argIndex);
-                    fprintf(out, "%s    pos += INT_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_FLOAT:
-                    requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
-                    fprintf(out, "%s    buff[pos] = FLOAT_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyFloat(buff, pos + 1, arg%d);\n", indent.c_str(),
-                            argIndex);
-                    fprintf(out, "%s    pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_LONG:
-                    fprintf(out, "%s    buff[pos] = LONG_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyLong(buff, pos + 1, arg%d);\n", indent.c_str(),
-                            argIndex);
-                    fprintf(out, "%s    pos += LONG_TYPE_SIZE;\n", indent.c_str());
-                    break;
-                case JAVA_TYPE_STRING:
-                    fprintf(out, "%s    buff[pos] = STRING_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyInt(buff, pos + 1, arg%dBytes.length);\n",
-                            indent.c_str(), argIndex);
-                    fprintf(out,
-                            "%s    System.arraycopy("
-                            "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, "
-                            "arg%dBytes.length);\n",
-                            indent.c_str(), argIndex, argIndex);
-                    fprintf(out, "%s    pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
-                            indent.c_str(), argIndex);
-                    break;
-                case JAVA_TYPE_BYTE_ARRAY:
-                    fprintf(out, "%s    buff[pos] = STRING_TYPE;\n", indent.c_str());
-                    fprintf(out, "%s    copyInt(buff, pos + 1, arg%d.length);\n", indent.c_str(),
-                            argIndex);
-                    fprintf(out,
-                            "%s    System.arraycopy("
-                            "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n",
-                            indent.c_str(), argIndex, argIndex);
-                    fprintf(out, "%s    pos += STRING_TYPE_OVERHEAD + arg%d.length;\n",
-                            indent.c_str(), argIndex);
-                    break;
-                case JAVA_TYPE_ATTRIBUTION_CHAIN: {
-                    requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION;
-                    const char* uidName = attributionDecl.fields.front().name.c_str();
-                    const char* tagName = attributionDecl.fields.back().name.c_str();
-
-                    fprintf(out, "%s    writeAttributionChain(buff, pos, %s, %s);\n",
-                            indent.c_str(), uidName, tagName);
-                    fprintf(out, "%s    pos += attrSize;\n", indent.c_str());
-                    break;
-                }
-                case JAVA_TYPE_KEY_VALUE_PAIR:
-                    requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
-                    requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS;
-                    fprintf(out,
-                            "%s    writeKeyValuePairs(buff, pos, (byte) count, intMap, "
-                            "longMap, "
-                            "stringMap, floatMap);\n",
-                            indent.c_str());
-                    fprintf(out, "%s    pos += keyValuePairSize;\n", indent.c_str());
-                    break;
-                default:
-                    // Unsupported types: OBJECT, DOUBLE.
-                    fprintf(stderr, "Object and Double are not supported in module logging");
-                    return 1;
-            }
-            argIndex++;
-        }
-
-        fprintf(out, "%s    StatsLog.writeRaw(buff, pos);\n", indent.c_str());
-        fprintf(out, "%s}\n", indent.c_str());
-        fprintf(out, "\n");
-    }
-
-    write_java_helpers_for_q_schema_methods(out, attributionDecl, requiredHelpers, indent);
-
-    return 0;
-}
-
-void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl,
-                                             const int requiredHelpers, const string& indent) {
-    fprintf(out, "\n");
-    fprintf(out, "%s// Helper methods for copying primitives\n", indent.c_str());
-    fprintf(out, "%sprivate static void copyInt(byte[] buff, int pos, int val) {\n",
-            indent.c_str());
-    fprintf(out, "%s    buff[pos] = (byte) (val);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
-    fprintf(out, "%s    return;\n", indent.c_str());
-    fprintf(out, "%s}\n", indent.c_str());
-    fprintf(out, "\n");
-
-    fprintf(out, "%sprivate static void copyLong(byte[] buff, int pos, long val) {\n",
-            indent.c_str());
-    fprintf(out, "%s    buff[pos] = (byte) (val);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 4] = (byte) (val >> 32);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 5] = (byte) (val >> 40);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 6] = (byte) (val >> 48);\n", indent.c_str());
-    fprintf(out, "%s    buff[pos + 7] = (byte) (val >> 56);\n", indent.c_str());
-    fprintf(out, "%s    return;\n", indent.c_str());
-    fprintf(out, "%s}\n", indent.c_str());
-    fprintf(out, "\n");
-
-    if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) {
-        fprintf(out, "%sprivate static void copyFloat(byte[] buff, int pos, float val) {\n",
-                indent.c_str());
-        fprintf(out, "%s    copyInt(buff, pos, Float.floatToIntBits(val));\n", indent.c_str());
-        fprintf(out, "%s    return;\n", indent.c_str());
-        fprintf(out, "%s}\n", indent.c_str());
-        fprintf(out, "\n");
-    }
-
-    if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) {
-        fprintf(out, "%sprivate static void writeAttributionChain(byte[] buff, int pos",
-                indent.c_str());
-        for (const auto& chainField : attributionDecl.fields) {
-            fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str());
-        }
-        fprintf(out, ") {\n");
-
-        const char* uidName = attributionDecl.fields.front().name.c_str();
-        const char* tagName = attributionDecl.fields.back().name.c_str();
-
-        // Write the first list begin.
-        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s    buff[pos + 1] = (byte) (%s.length);\n", indent.c_str(), tagName);
-        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
-        // Iterate through the attribution chain and write the nodes.
-        fprintf(out, "%s    for (int i = 0; i < %s.length; i++) {\n", indent.c_str(), tagName);
-        // Write the list begin.
-        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos + 1] = %lu;\n", indent.c_str(),
-                attributionDecl.fields.size());
-        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
-        // Write the uid.
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, %s[i]);\n", indent.c_str(), uidName);
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-
-        // Write the tag.
-        fprintf(out, "%s        String %sStr = (%s[i] == null) ? \"\" : %s[i];\n", indent.c_str(),
-                tagName, tagName, tagName);
-        fprintf(out,
-                "%s        byte[] %sByte = "
-                "%sStr.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
-                indent.c_str(), tagName, tagName);
-        fprintf(out, "%s        buff[pos] = STRING_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, %sByte.length);\n", indent.c_str(), tagName);
-        fprintf(out,
-                "%s        System.arraycopy("
-                "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n",
-                indent.c_str(), tagName, tagName);
-        fprintf(out, "%s        pos += STRING_TYPE_OVERHEAD + %sByte.length;\n", indent.c_str(),
-                tagName);
-        fprintf(out, "%s    }\n", indent.c_str());
-        fprintf(out, "%s}\n", indent.c_str());
-        fprintf(out, "\n");
-    }
-
-    if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) {
-        fprintf(out,
-                "%sprivate static void writeKeyValuePairs(byte[] buff, int pos, "
-                "byte numPairs,\n",
-                indent.c_str());
-        fprintf(out, "%s        final android.util.SparseIntArray intMap,\n", indent.c_str());
-        fprintf(out, "%s        final android.util.SparseLongArray longMap,\n", indent.c_str());
-        fprintf(out, "%s        final android.util.SparseArray<String> stringMap,\n",
-                indent.c_str());
-        fprintf(out, "%s        final android.util.SparseArray<Float> floatMap) {\n",
-                indent.c_str());
-
-        // Start list of lists.
-        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s    buff[pos + 1] = (byte) numPairs;\n", indent.c_str());
-        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
-        // Write integers.
-        fprintf(out, "%s    final int intMapSize = null == intMap ? 0 : intMap.size();\n",
-                indent.c_str());
-        fprintf(out, "%s    for (int i = 0; i < intMapSize; i++) {\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
-        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-        fprintf(out, "%s        final int key = intMap.keyAt(i);\n", indent.c_str());
-        fprintf(out, "%s        final int value = intMap.valueAt(i);\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, value);\n", indent.c_str());
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s    }\n", indent.c_str());
-
-        // Write longs.
-        fprintf(out, "%s    final int longMapSize = null == longMap ? 0 : longMap.size();\n",
-                indent.c_str());
-        fprintf(out, "%s    for (int i = 0; i < longMapSize; i++) {\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
-        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-        fprintf(out, "%s        final int key = longMap.keyAt(i);\n", indent.c_str());
-        fprintf(out, "%s        final long value = longMap.valueAt(i);\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = LONG_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyLong(buff, pos + 1, value);\n", indent.c_str());
-        fprintf(out, "%s        pos += LONG_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s    }\n", indent.c_str());
-
-        // Write Strings.
-        fprintf(out,
-                "%s    final int stringMapSize = null == stringMap ? 0 : "
-                "stringMap.size();\n",
-                indent.c_str());
-        fprintf(out, "%s    for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
-        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-        fprintf(out, "%s        final int key = stringMap.keyAt(i);\n", indent.c_str());
-        fprintf(out, "%s        final String value = stringMap.valueAt(i);\n", indent.c_str());
-        fprintf(out,
-                "%s        final byte[] valueBytes = "
-                "value.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
-                indent.c_str());
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = STRING_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, valueBytes.length);\n", indent.c_str());
-        fprintf(out,
-                "%s        System.arraycopy("
-                "valueBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, "
-                "valueBytes.length);\n",
-                indent.c_str());
-        fprintf(out, "%s        pos += STRING_TYPE_OVERHEAD + valueBytes.length;\n",
-                indent.c_str());
-        fprintf(out, "%s    }\n", indent.c_str());
-
-        // Write floats.
-        fprintf(out,
-                "%s    final int floatMapSize = null == floatMap ? 0 : "
-                "floatMap.size();\n",
-                indent.c_str());
-        fprintf(out, "%s    for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
-        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-        fprintf(out, "%s        final int key = floatMap.keyAt(i);\n", indent.c_str());
-        fprintf(out, "%s        final float value = floatMap.valueAt(i);\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
-        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s        buff[pos] = FLOAT_TYPE;\n", indent.c_str());
-        fprintf(out, "%s        copyFloat(buff, pos + 1, value);\n", indent.c_str());
-        fprintf(out, "%s        pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
-        fprintf(out, "%s    }\n", indent.c_str());
-        fprintf(out, "%s}\n", indent.c_str());
-        fprintf(out, "\n");
-    }
-}
-
-// This method is called in main.cpp to generate StatsLog for modules that's
-// compatible with Q at compile-time.
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
-                                      const AtomDecl& attributionDecl, const string& javaClass,
-                                      const string& javaPackage, const bool supportWorkSource) {
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-    fprintf(out, "package %s;\n", javaPackage.c_str());
-    fprintf(out, "\n");
-    fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
-    fprintf(out, "\n");
-    fprintf(out, "import android.util.StatsLog;\n");
-    fprintf(out, "import android.os.SystemClock;\n");
-    fprintf(out, "\n");
-    fprintf(out, "\n");
-    fprintf(out, "/**\n");
-    fprintf(out, " * Utility class for logging statistics events.\n");
-    fprintf(out, " */\n");
-    fprintf(out, "public class %s {\n", javaClass.c_str());
-
-    write_java_q_logging_constants(out, "    ");
-
-    write_java_atom_codes(out, atoms);
-
-    write_java_enum_values(out, atoms);
-
-    int errors = 0;
-    // Print write methods
-    fprintf(out, "    // Write methods\n");
-    errors += write_java_methods_q_schema(out, atoms.signatureInfoMap, attributionDecl, "    ");
-    errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap);
-    if (supportWorkSource) {
-        errors += write_java_work_source_methods(out, atoms.signatureInfoMap);
-    }
-
-    fprintf(out, "}\n");
-
-    return errors;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
deleted file mode 100644
index 622ef3e..0000000
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ /dev/null
@@ -1,47 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
-#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-void write_java_q_logging_constants(FILE* out, const string& indent);
-
-int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                                const AtomDecl& attributionDecl, const string& indent);
-
-void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl,
-                                             const int requiredHelpers, const string& indent);
-
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
-                                      const AtomDecl& attributionDecl, const string& javaClass,
-                                      const string& javaPackage, const bool supportWorkSource);
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-#endif  // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
deleted file mode 100644
index 50f81760..0000000
--- a/tools/stats_log_api_gen/main.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-#include "frameworks/proto_logging/stats/atoms.pb.h"
-#include "java_writer.h"
-#include "java_writer_q.h"
-#include "native_writer.h"
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using android::os::statsd::Atom;
-
-static void print_usage() {
-    fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "OPTIONS\n");
-    fprintf(stderr, "  --cpp FILENAME       the header file to output for write helpers\n");
-    fprintf(stderr, "  --header FILENAME    the cpp file to output for write helpers\n");
-    fprintf(stderr, "  --help               this message\n");
-    fprintf(stderr, "  --java FILENAME      the java file to output\n");
-    fprintf(stderr, "  --module NAME        optional, module name to generate outputs for\n");
-    fprintf(stderr,
-            "  --namespace COMMA,SEP,NAMESPACE   required for cpp/header with "
-            "module\n");
-    fprintf(stderr,
-            "                                    comma separated namespace of "
-            "the files\n");
-    fprintf(stderr,
-            "  --importHeader NAME  required for cpp/jni to say which header to "
-            "import "
-            "for write helpers\n");
-    fprintf(stderr, "  --javaPackage PACKAGE             the package for the java file.\n");
-    fprintf(stderr, "                                    required for java with module\n");
-    fprintf(stderr, "  --javaClass CLASS    the class name of the java class.\n");
-    fprintf(stderr, "                       Optional for Java with module.\n");
-    fprintf(stderr, "                       Default is \"StatsLogInternal\"\n");
-    fprintf(stderr, "  --supportQ           Include runtime support for Android Q.\n");
-    fprintf(stderr,
-            "  --worksource         Include support for logging WorkSource "
-            "objects.\n");
-    fprintf(stderr,
-            "  --compileQ           Include compile-time support for Android Q "
-            "(Java only).\n");
-}
-
-/**
- * Do the argument parsing and execute the tasks.
- */
-static int run(int argc, char const* const* argv) {
-    string cppFilename;
-    string headerFilename;
-    string javaFilename;
-    string javaPackage;
-    string javaClass;
-
-    string moduleName = DEFAULT_MODULE_NAME;
-    string cppNamespace = DEFAULT_CPP_NAMESPACE;
-    string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT;
-    bool supportQ = false;
-    bool supportWorkSource = false;
-    bool compileQ = false;
-
-    int index = 1;
-    while (index < argc) {
-        if (0 == strcmp("--help", argv[index])) {
-            print_usage();
-            return 0;
-        } else if (0 == strcmp("--cpp", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            cppFilename = argv[index];
-        } else if (0 == strcmp("--header", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            headerFilename = argv[index];
-        } else if (0 == strcmp("--java", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            javaFilename = argv[index];
-        } else if (0 == strcmp("--module", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            moduleName = argv[index];
-        } else if (0 == strcmp("--namespace", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            cppNamespace = argv[index];
-        } else if (0 == strcmp("--importHeader", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            cppHeaderImport = argv[index];
-        } else if (0 == strcmp("--javaPackage", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            javaPackage = argv[index];
-        } else if (0 == strcmp("--javaClass", argv[index])) {
-            index++;
-            if (index >= argc) {
-                print_usage();
-                return 1;
-            }
-            javaClass = argv[index];
-        } else if (0 == strcmp("--supportQ", argv[index])) {
-            supportQ = true;
-        } else if (0 == strcmp("--worksource", argv[index])) {
-            supportWorkSource = true;
-        } else if (0 == strcmp("--compileQ", argv[index])) {
-            compileQ = true;
-        }
-
-        index++;
-    }
-
-    if (cppFilename.empty() && headerFilename.empty() && javaFilename.empty()) {
-        print_usage();
-        return 1;
-    }
-
-    if (DEFAULT_MODULE_NAME == moduleName && (supportQ || compileQ)) {
-        // Support for Q schema is not needed for default module.
-        fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
-        return 1;
-    }
-
-    if (supportQ && compileQ) {
-        // Runtime Q support is redundant if compile-time Q support is required.
-        fprintf(stderr, "Cannot specify compileQ and supportQ simultaneously.\n");
-        return 1;
-    }
-
-    // Collate the parameters
-    Atoms atoms;
-    int errorCount = collate_atoms(Atom::descriptor(), moduleName, &atoms);
-    if (errorCount != 0) {
-        return 1;
-    }
-
-    AtomDecl attributionDecl;
-    vector<java_type_t> attributionSignature;
-    collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
-                 &attributionSignature);
-
-    // Write the .cpp file
-    if (!cppFilename.empty()) {
-        FILE* out = fopen(cppFilename.c_str(), "w");
-        if (out == nullptr) {
-            fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
-            return 1;
-        }
-        // If this is for a specific module, the namespace must also be provided.
-        if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
-            fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
-            return 1;
-        }
-        // If this is for a specific module, the header file to import must also be
-        // provided.
-        if (moduleName != DEFAULT_MODULE_NAME && cppHeaderImport == DEFAULT_CPP_HEADER_IMPORT) {
-            fprintf(stderr, "Must supply --headerImport if supplying a specific module\n");
-            return 1;
-        }
-        errorCount = android::stats_log_api_gen::write_stats_log_cpp(
-                out, atoms, attributionDecl, cppNamespace, cppHeaderImport, supportQ);
-        fclose(out);
-    }
-
-    // Write the .h file
-    if (!headerFilename.empty()) {
-        FILE* out = fopen(headerFilename.c_str(), "w");
-        if (out == nullptr) {
-            fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
-            return 1;
-        }
-        // If this is for a specific module, the namespace must also be provided.
-        if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
-            fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
-        }
-        errorCount = android::stats_log_api_gen::write_stats_log_header(out, atoms, attributionDecl,
-                                                                        cppNamespace);
-        fclose(out);
-    }
-
-    // Write the .java file
-    if (!javaFilename.empty()) {
-        if (javaClass.empty()) {
-            fprintf(stderr, "Must supply --javaClass if supplying a Java filename");
-            return 1;
-        }
-
-        if (javaPackage.empty()) {
-            fprintf(stderr, "Must supply --javaPackage if supplying a Java filename");
-            return 1;
-        }
-
-        if (moduleName.empty()) {
-            fprintf(stderr, "Must supply --module if supplying a Java filename");
-            return 1;
-        }
-
-        FILE* out = fopen(javaFilename.c_str(), "w");
-        if (out == nullptr) {
-            fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
-            return 1;
-        }
-
-        if (compileQ) {
-            errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module(
-                    out, atoms, attributionDecl, javaClass, javaPackage, supportWorkSource);
-        } else {
-            errorCount = android::stats_log_api_gen::write_stats_log_java(
-                    out, atoms, attributionDecl, javaClass, javaPackage, supportQ,
-                    supportWorkSource);
-        }
-
-        fclose(out);
-    }
-
-    return errorCount;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-/**
- * Main.
- */
-int main(int argc, char const* const* argv) {
-    GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-    return android::stats_log_api_gen::run(argc, argv);
-}
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
deleted file mode 100644
index b4fb8dd..0000000
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ /dev/null
@@ -1,423 +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.
- */
-
-#include "native_writer.h"
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-static void write_native_annotation_constants(FILE* out) {
-    fprintf(out, "// Annotation constants.\n");
-
-    const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
-    for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
-        fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id);
-    }
-    fprintf(out, "\n");
-}
-
-static void write_annotations(FILE* out, int argIndex,
-                              const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
-                              const string& methodPrefix, const string& methodSuffix) {
-    FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
-            fieldNumberToAtomDeclSet.find(argIndex);
-    if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
-        return;
-    }
-    const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
-    const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
-    for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
-        const string atomConstant = make_constant_name(atomDecl->name);
-        fprintf(out, "    if (%s == code) {\n", atomConstant.c_str());
-        const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
-        int resetState = -1;
-        int defaultState = -1;
-        for (const shared_ptr<Annotation>& annotation : annotations) {
-            const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
-            switch (annotation->type) {
-                case ANNOTATION_TYPE_INT:
-                    if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
-                        resetState = annotation->value.intValue;
-                    } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
-                        defaultState = annotation->value.intValue;
-                    } else {
-                        fprintf(out, "        %saddInt32Annotation(%s%s, %d);\n",
-                                methodPrefix.c_str(), methodSuffix.c_str(),
-                                annotationConstant.c_str(), annotation->value.intValue);
-                    }
-                    break;
-                case ANNOTATION_TYPE_BOOL:
-                    fprintf(out, "        %saddBoolAnnotation(%s%s, %s);\n", methodPrefix.c_str(),
-                            methodSuffix.c_str(), annotationConstant.c_str(),
-                            annotation->value.boolValue ? "true" : "false");
-                    break;
-                default:
-                    break;
-            }
-        }
-        if (defaultState != -1 && resetState != -1) {
-            const string& annotationConstant =
-                    ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
-            fprintf(out, "        if (arg%d == %d) {\n", argIndex, resetState);
-            fprintf(out, "            %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(),
-                    methodSuffix.c_str(), annotationConstant.c_str(), defaultState);
-            fprintf(out, "        }\n");
-        }
-        fprintf(out, "    }\n");
-    }
-}
-
-static int write_native_method_body(FILE* out, vector<java_type_t>& signature,
-                                    const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
-                                    const AtomDecl& attributionDecl) {
-    int argIndex = 1;
-    fprintf(out, "    AStatsEvent_setAtomId(event, code);\n");
-    write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
-                      "event, ");
-    for (vector<java_type_t>::const_iterator arg = signature.begin();
-         arg != signature.end(); arg++) {
-        switch (*arg) {
-            case JAVA_TYPE_ATTRIBUTION_CHAIN: {
-                const char* uidName = attributionDecl.fields.front().name.c_str();
-                const char* tagName = attributionDecl.fields.back().name.c_str();
-                fprintf(out,
-                        "    AStatsEvent_writeAttributionChain(event, "
-                        "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
-                        "static_cast<uint8_t>(%s_length));\n",
-                        uidName, tagName, uidName);
-                break;
-            }
-            case JAVA_TYPE_BYTE_ARRAY:
-                fprintf(out,
-                        "    AStatsEvent_writeByteArray(event, "
-                        "reinterpret_cast<const uint8_t*>(arg%d.arg), "
-                        "arg%d.arg_length);\n",
-                        argIndex, argIndex);
-                break;
-            case JAVA_TYPE_BOOLEAN:
-                fprintf(out, "    AStatsEvent_writeBool(event, arg%d);\n", argIndex);
-                break;
-            case JAVA_TYPE_INT:  // Fall through.
-            case JAVA_TYPE_ENUM:
-                fprintf(out, "    AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
-                break;
-            case JAVA_TYPE_FLOAT:
-                fprintf(out, "    AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
-                break;
-            case JAVA_TYPE_LONG:
-                fprintf(out, "    AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
-                break;
-            case JAVA_TYPE_STRING:
-                fprintf(out, "    AStatsEvent_writeString(event, arg%d);\n", argIndex);
-                break;
-            default:
-                // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS
-                fprintf(stderr, "Encountered unsupported type.");
-                return 1;
-        }
-        write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
-                          "event, ");
-        argIndex++;
-    }
-    return 0;
-}
-
-static int write_native_stats_write_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
-                                            const AtomDecl& attributionDecl, const bool supportQ) {
-    fprintf(out, "\n");
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-        const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
-        // Key value pairs not supported in native.
-        if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
-            signature.end()) {
-            continue;
-        }
-        write_native_method_signature(out, "int stats_write(", signature, attributionDecl, " {");
-
-        // Write method body.
-        if (supportQ) {
-            int argIndex = 1;
-            fprintf(out, "    StatsEventCompat event;\n");
-            fprintf(out, "    event.setAtomId(code);\n");
-            write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", "");
-            for (vector<java_type_t>::const_iterator arg = signature.begin();
-                 arg != signature.end(); arg++) {
-                switch (*arg) {
-                    case JAVA_TYPE_ATTRIBUTION_CHAIN: {
-                        const char* uidName = attributionDecl.fields.front().name.c_str();
-                        const char* tagName = attributionDecl.fields.back().name.c_str();
-                        fprintf(out, "    event.writeAttributionChain(%s, %s_length, %s);\n",
-                                uidName, uidName, tagName);
-                        break;
-                    }
-                    case JAVA_TYPE_BYTE_ARRAY:
-                        fprintf(out, "    event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
-                                argIndex, argIndex);
-                        break;
-                    case JAVA_TYPE_BOOLEAN:
-                        fprintf(out, "    event.writeBool(arg%d);\n", argIndex);
-                        break;
-                    case JAVA_TYPE_INT:  // Fall through.
-                    case JAVA_TYPE_ENUM:
-                        fprintf(out, "    event.writeInt32(arg%d);\n", argIndex);
-                        break;
-                    case JAVA_TYPE_FLOAT:
-                        fprintf(out, "    event.writeFloat(arg%d);\n", argIndex);
-                        break;
-                    case JAVA_TYPE_LONG:
-                        fprintf(out, "    event.writeInt64(arg%d);\n", argIndex);
-                        break;
-                    case JAVA_TYPE_STRING:
-                        fprintf(out, "    event.writeString(arg%d);\n", argIndex);
-                        break;
-                    default:
-                        // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS.
-                        fprintf(stderr, "Encountered unsupported type.");
-                        return 1;
-                }
-                write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", "");
-                argIndex++;
-            }
-            fprintf(out, "    return event.writeToSocket();\n"); // end method body.
-        } else {
-            fprintf(out, "    AStatsEvent* event = AStatsEvent_obtain();\n");
-            int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
-                                               attributionDecl);
-            if (ret != 0) {
-                return ret;
-            }
-            fprintf(out, "    const int ret = AStatsEvent_write(event);\n");
-            fprintf(out, "    AStatsEvent_release(event);\n");
-            fprintf(out, "    return ret;\n"); // end method body.
-        }
-        fprintf(out, "}\n\n"); // end method.
-    }
-    return 0;
-}
-
-static void write_native_stats_write_non_chained_methods(FILE* out,
-                                                         const SignatureInfoMap& signatureInfoMap,
-                                                         const AtomDecl& attributionDecl) {
-    fprintf(out, "\n");
-    for (auto signature_it = signatureInfoMap.begin();
-         signature_it != signatureInfoMap.end(); signature_it++) {
-        vector<java_type_t> signature = signature_it->first;
-        // Key value pairs not supported in native.
-        if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
-            signature.end()) {
-            continue;
-        }
-
-        write_native_method_signature(out, "int stats_write_non_chained(", signature,
-                                      attributionDecl, " {");
-
-        vector<java_type_t> newSignature;
-
-        // First two args form the attribution node so size goes down by 1.
-        newSignature.reserve(signature.size() - 1);
-
-        // First arg is Attribution Chain.
-        newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
-
-        // Followed by the originial signature except the first 2 args.
-        newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
-
-        const char* uidName = attributionDecl.fields.front().name.c_str();
-        const char* tagName = attributionDecl.fields.back().name.c_str();
-        fprintf(out, "    const int32_t* %s = &arg1;\n", uidName);
-        fprintf(out, "    const size_t %s_length = 1;\n", uidName);
-        fprintf(out, "    const std::vector<char const*> %s(1, arg2);\n", tagName);
-        fprintf(out, "    return ");
-        write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
-
-        fprintf(out, "}\n\n");
-    }
-}
-
-static int write_native_build_stats_event_methods(FILE* out,
-                                                  const SignatureInfoMap& signatureInfoMap,
-                                                  const AtomDecl& attributionDecl) {
-    fprintf(out, "\n");
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-        const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
-        // Key value pairs not supported in native.
-        if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
-            signature.end()) {
-            continue;
-        }
-        write_native_method_signature(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
-                                      signature, attributionDecl, " {");
-
-        fprintf(out, "    AStatsEvent* event = AStatsEventList_addStatsEvent(pulled_data);\n");
-        int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
-                                           attributionDecl);
-        if (ret != 0) {
-            return ret;
-        }
-        fprintf(out, "    AStatsEvent_build(event);\n"); // end method body.
-
-        fprintf(out, "}\n\n"); // end method.
-    }
-    return 0;
-}
-
-static void write_native_method_header(FILE* out, const string& methodName,
-                                       const SignatureInfoMap& signatureInfoMap,
-                                       const AtomDecl& attributionDecl) {
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-
-        // Key value pairs not supported in native.
-        if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
-            signature.end()) {
-            continue;
-        }
-        write_native_method_signature(out, methodName, signature, attributionDecl, ";");
-    }
-}
-
-int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                        const string& cppNamespace, const string& importHeader,
-                        const bool supportQ) {
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-
-    fprintf(out, "#include <%s>\n", importHeader.c_str());
-    if (supportQ) {
-        fprintf(out, "#include <StatsEventCompat.h>\n");
-    } else {
-        fprintf(out, "#include <stats_event.h>\n");
-
-        if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
-            fprintf(out, "#include <stats_pull_atom_callback.h>\n");
-        }
-    }
-
-
-
-    fprintf(out, "\n");
-    write_namespace(out, cppNamespace);
-
-    write_native_stats_write_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
-    write_native_stats_write_non_chained_methods(out, atoms.nonChainedSignatureInfoMap,
-                                                 attributionDecl);
-    write_native_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap,
-                                           attributionDecl);
-
-    // Print footer
-    fprintf(out, "\n");
-    write_closing_namespace(out, cppNamespace);
-
-    return 0;
-}
-
-int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                           const string& cppNamespace) {
-    // Print prelude
-    fprintf(out, "// This file is autogenerated\n");
-    fprintf(out, "\n");
-    fprintf(out, "#pragma once\n");
-    fprintf(out, "\n");
-    fprintf(out, "#include <stdint.h>\n");
-    fprintf(out, "#include <vector>\n");
-    fprintf(out, "#include <map>\n");
-    fprintf(out, "#include <set>\n");
-    if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
-        fprintf(out, "#include <stats_pull_atom_callback.h>\n");
-    }
-    fprintf(out, "\n");
-
-    write_namespace(out, cppNamespace);
-    fprintf(out, "\n");
-    fprintf(out, "/*\n");
-    fprintf(out, " * API For logging statistics events.\n");
-    fprintf(out, " */\n");
-    fprintf(out, "\n");
-
-    write_native_atom_constants(out, atoms, attributionDecl);
-
-    // Print constants for the enum values.
-    fprintf(out, "//\n");
-    fprintf(out, "// Constants for enum values\n");
-    fprintf(out, "//\n\n");
-    for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
-         atomIt++) {
-        for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
-             field != (*atomIt)->fields.end(); field++) {
-            if (field->javaType == JAVA_TYPE_ENUM) {
-                fprintf(out, "// Values for %s.%s\n", (*atomIt)->message.c_str(),
-                        field->name.c_str());
-                for (map<int, string>::const_iterator value = field->enumValues.begin();
-                     value != field->enumValues.end(); value++) {
-                    fprintf(out, "const int32_t %s__%s__%s = %d;\n",
-                            make_constant_name((*atomIt)->message).c_str(),
-                            make_constant_name(field->name).c_str(),
-                            make_constant_name(value->second).c_str(), value->first);
-                }
-                fprintf(out, "\n");
-            }
-        }
-    }
-
-    write_native_annotation_constants(out);
-
-    fprintf(out, "struct BytesField {\n");
-    fprintf(out,
-            "  BytesField(char const* array, size_t len) : arg(array), "
-            "arg_length(len) {}\n");
-    fprintf(out, "  char const* arg;\n");
-    fprintf(out, "  size_t arg_length;\n");
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-
-    // Print write methods
-    fprintf(out, "//\n");
-    fprintf(out, "// Write methods\n");
-    fprintf(out, "//\n");
-    write_native_method_header(out, "int stats_write(", atoms.signatureInfoMap, attributionDecl);
-    fprintf(out, "\n");
-
-    fprintf(out, "//\n");
-    fprintf(out, "// Write flattened methods\n");
-    fprintf(out, "//\n");
-    write_native_method_header(out, "int stats_write_non_chained(", atoms.nonChainedSignatureInfoMap,
-                               attributionDecl);
-    fprintf(out, "\n");
-
-    // Print pulled atoms methods.
-    fprintf(out, "//\n");
-    fprintf(out, "// Add AStatsEvent methods\n");
-    fprintf(out, "//\n");
-    write_native_method_header(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
-                               atoms.pulledAtomsSignatureInfoMap,
-                               attributionDecl);
-
-    fprintf(out, "\n");
-    write_closing_namespace(out, cppNamespace);
-
-    return 0;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
deleted file mode 100644
index 4e42d1f..0000000
--- a/tools/stats_log_api_gen/native_writer.h
+++ /dev/null
@@ -1,38 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
-#define ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                        const string& cppNamespace, const string& importHeader,
-                        const bool supportQ);
-
-int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
-                           const string& cppNamespace);
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-#endif  // ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
deleted file mode 100644
index 18c52bf..0000000
--- a/tools/stats_log_api_gen/test.proto
+++ /dev/null
@@ -1,236 +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.
- */
-
-syntax = "proto2";
-
-import "frameworks/proto_logging/stats/atoms.proto";
-import "frameworks/proto_logging/stats/atom_field_options.proto";
-
-package android.stats_log_api_gen;
-
-message IntAtom {
-    optional int32 field1 = 1;
-}
-
-message AnotherIntAtom {
-    optional int32 field1 = 1;
-}
-
-message OutOfOrderAtom {
-    optional int32 field2 = 2;
-    optional int32 field1 = 1;
-}
-
-enum AnEnum {
-    VALUE0 = 0;
-    VALUE1 = 1;
-}
-
-message AllTypesAtom {
-  repeated android.os.statsd.AttributionNode attribution_chain = 1;
-  optional float float_field = 2;
-  optional int64 int64_field = 3;
-  optional uint64 uint64_field = 4;
-  optional int32 int32_field = 5;
-  optional fixed64 fixed64_field = 6;
-  optional fixed32 fixed32_field = 7;
-  optional bool bool_field = 8;
-  optional string string_field = 9;
-  optional uint32 uint32_field = 10;
-  optional AnEnum enum_field = 11;
-  optional sfixed32 sfixed32_field = 12;
-  optional sfixed64 sfixed64_field = 13;
-  optional sint32 sint32_field = 14;
-  optional sint64 sint64_field = 15;
-}
-
-message Event {
-    oneof pushed {
-        OutOfOrderAtom out_of_order_atom = 2;
-        IntAtom int_atom = 1;
-        AnotherIntAtom another_int_atom = 3;
-        AllTypesAtom all_types_atom = 4;
-    }
-}
-
-message BadTypesAtom {
-    optional IntAtom bad_int_atom = 1;
-    optional bytes bad_bytes = 2;
-    repeated int32 repeated_field = 3;
-    optional double double_field = 4;
-}
-
-message BadTypesEvent {
-    oneof pushed {
-        BadTypesAtom bad_types_atom = 1;
-    }
-}
-
-message BadSkippedFieldSingleAtom {
-    optional int32 field2 = 2;
-}
-
-message BadSkippedFieldSingle {
-    oneof pushed {
-        BadSkippedFieldSingleAtom bad = 1;
-    }
-}
-
-message BadSkippedFieldMultipleAtom {
-    optional int32 field1 = 1;
-    optional int32 field3 = 3;
-    optional int32 field5 = 5;
-}
-
-message BadSkippedFieldMultiple {
-    oneof pushed {
-        BadSkippedFieldMultipleAtom bad = 1;
-    }
-}
-
-message BadAttributionNodePositionAtom {
-  optional int32 field1 = 1;
-  repeated android.os.statsd.AttributionNode attribution = 2;
-}
-
-message BadAttributionNodePosition {
-  oneof pushed { BadAttributionNodePositionAtom bad = 1; }
-}
-
-message GoodEventWithBinaryFieldAtom {
-    oneof pushed { GoodBinaryFieldAtom field1 = 1; }
-}
-
-message ComplexField {
-    optional string str = 1;
-}
-
-message GoodBinaryFieldAtom {
-    optional int32 field1 = 1;
-    optional ComplexField bf = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
-}
-
-message BadEventWithBinaryFieldAtom {
-    oneof pushed { BadBinaryFieldAtom field1 = 1; }
-}
-
-message BadBinaryFieldAtom {
-    optional int32 field1 = 1;
-    optional ComplexField bf = 2;
-}
-
-message BadStateAtoms {
-    oneof pushed {
-        BadStateAtom1 bad1 = 1;
-        BadStateAtom2 bad2 = 2;
-        BadStateAtom3 bad3 = 3;
-    }
-}
-
-message GoodStateAtoms {
-    oneof pushed {
-        GoodStateAtom1 good1 = 1;
-        GoodStateAtom2 good2 = 2;
-    }
-}
-
-// The atom has only primary field but no exclusive state field.
-message BadStateAtom1 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
-}
-
-// Only primative types can be annotated.
-message BadStateAtom2 {
-    repeated android.os.statsd.AttributionNode attribution = 1
-            [(android.os.statsd.state_field_option).primary_field = true];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// Having 2 exclusive state field in the atom means the atom is badly designed.
-// E.g., putting bluetooth state and wifi state in the same atom.
-message BadStateAtom3 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-    optional int32 state2 = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message GoodStateAtom1 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
-    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// Atoms can have exclusive state field, but no primary field. That means
-// the state is globally exclusive (e.g., DisplayState).
-message GoodStateAtom2 {
-    optional int32 uid = 1;
-    optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// We can have more than one primary fields. That means their combination is a
-// primary key.
-message GoodStateAtom3 {
-    optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
-    optional int32 tid = 2 [(android.os.statsd.state_field_option).primary_field = true];
-    optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message ModuleOneAtom {
-    optional int32 field = 1 [(android.os.statsd.is_uid) = true];
-}
-
-message ModuleTwoAtom {
-    optional int32 field = 1;
-}
-
-message ModuleOneAndTwoAtom {
-    optional int32 field = 1 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message NoModuleAtom {
-    optional string field = 1;
-}
-
-message ModuleAtoms {
-    oneof pushed {
-        ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"];
-        ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"];
-        ModuleOneAndTwoAtom module_one_and_two_atom = 3 [
-                (android.os.statsd.module) = "module1", (android.os.statsd.module) = "module2"
-        ];
-        NoModuleAtom no_module_atom = 4;
-    }
-}
-
-message NotAPushNorPullAtom {
-    oneof event {
-        IntAtom int_atom = 1;
-    }
-}
-
-message AtomNotInAOneof {
-    optional IntAtom int_atom = 1;
-}
-
-message PushedAndPulledAtoms {
-    oneof pushed {
-        IntAtom int_atom_1 = 1;
-    }
-
-    oneof pulled {
-        OutOfOrderAtom out_of_order_atom = 11;
-        AnotherIntAtom another_int_atom = 10;
-    }
-}
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
deleted file mode 100644
index 6f78921..0000000
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ /dev/null
@@ -1,432 +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 <gtest/gtest.h>
-#include <stdio.h>
-
-#include "Collation.h"
-#include "frameworks/base/tools/stats_log_api_gen/test.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using std::map;
-using std::vector;
-
-/**
- * Return whether the map contains a vector of the elements provided.
- */
-static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) {
-    va_list args;
-    vector<java_type_t> v(count);
-
-    va_start(args, count);
-    for (int i = 0; i < count; i++) {
-        v[i] = static_cast<java_type_t>(va_arg(args, int));
-    }
-    va_end(args);
-
-    return s.find(v) != s.end();
-}
-
-/**
- * Expect that the provided map contains the elements provided.
- */
-#define EXPECT_MAP_CONTAINS_SIGNATURE(s, ...)                    \
-    do {                                                         \
-        int count = sizeof((int[]){__VA_ARGS__}) / sizeof(int);  \
-        EXPECT_TRUE(map_contains_vector(s, count, __VA_ARGS__)); \
-    } while (0)
-
-/** Expects that the provided atom has no enum values for any field. */
-#define EXPECT_NO_ENUM_FIELD(atom)                                           \
-    do {                                                                     \
-        for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
-             field != atom->fields.end(); field++) {                         \
-            EXPECT_TRUE(field->enumValues.empty());                          \
-        }                                                                    \
-    } while (0)
-
-/** Expects that exactly one specific field has expected enum values. */
-#define EXPECT_HAS_ENUM_FIELD(atom, field_name, values)                      \
-    do {                                                                     \
-        for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
-             field != atom->fields.end(); field++) {                         \
-            if (field->name == field_name) {                                 \
-                EXPECT_EQ(field->enumValues, values);                        \
-            } else {                                                         \
-                EXPECT_TRUE(field->enumValues.empty());                      \
-            }                                                                \
-        }                                                                    \
-    } while (0)
-
-/**
- * Test a correct collation, with all the types.
- */
-TEST(CollationTest, CollateStats) {
-    Atoms atoms;
-    int errorCount = collate_atoms(Event::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(0, errorCount);
-    EXPECT_EQ(3ul, atoms.signatureInfoMap.size());
-
-    // IntAtom, AnotherIntAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
-    // OutOfOrderAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
-
-    // AllTypesAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap,
-                                  JAVA_TYPE_ATTRIBUTION_CHAIN,  // AttributionChain
-                                  JAVA_TYPE_FLOAT,              // float
-                                  JAVA_TYPE_LONG,               // int64
-                                  JAVA_TYPE_LONG,               // uint64
-                                  JAVA_TYPE_INT,                // int32
-                                  JAVA_TYPE_LONG,               // fixed64
-                                  JAVA_TYPE_INT,                // fixed32
-                                  JAVA_TYPE_BOOLEAN,            // bool
-                                  JAVA_TYPE_STRING,             // string
-                                  JAVA_TYPE_INT,                // uint32
-                                  JAVA_TYPE_INT,                // AnEnum
-                                  JAVA_TYPE_INT,                // sfixed32
-                                  JAVA_TYPE_LONG,               // sfixed64
-                                  JAVA_TYPE_INT,                // sint32
-                                  JAVA_TYPE_LONG                // sint64
-    );
-
-    EXPECT_EQ(4ul, atoms.decls.size());
-
-    AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
-    EXPECT_EQ(1, (*atomIt)->code);
-    EXPECT_EQ("int_atom", (*atomIt)->name);
-    EXPECT_EQ("IntAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(2, (*atomIt)->code);
-    EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
-    EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(3, (*atomIt)->code);
-    EXPECT_EQ("another_int_atom", (*atomIt)->name);
-    EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(4, (*atomIt)->code);
-    EXPECT_EQ("all_types_atom", (*atomIt)->name);
-    EXPECT_EQ("AllTypesAtom", (*atomIt)->message);
-    map<int, string> enumValues;
-    enumValues[0] = "VALUE0";
-    enumValues[1] = "VALUE1";
-    EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues);
-    atomIt++;
-
-    EXPECT_EQ(atoms.decls.end(), atomIt);
-}
-
-/**
- * Test that event class that contains stuff other than the atoms is rejected.
- */
-TEST(CollationTest, NonMessageTypeFails) {
-    Atoms atoms;
-    int errorCount = collate_atoms(IntAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that atoms that have non-primitive types or repeated fields are
- * rejected.
- */
-TEST(CollationTest, FailOnBadTypes) {
-    Atoms atoms;
-    int errorCount = collate_atoms(BadTypesEvent::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(4, errorCount);
-}
-
-/**
- * Test that atoms that skip field numbers (in the first position) are rejected.
- */
-TEST(CollationTest, FailOnSkippedFieldsSingle) {
-    Atoms atoms;
-    int errorCount =
-            collate_atoms(BadSkippedFieldSingle::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that atoms that skip field numbers (not in the first position, and
- * multiple times) are rejected.
- */
-TEST(CollationTest, FailOnSkippedFieldsMultiple) {
-    Atoms atoms;
-    int errorCount =
-            collate_atoms(BadSkippedFieldMultiple::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(2, errorCount);
-}
-
-/**
- * Test that atoms that have an attribution chain not in the first position are
- * rejected.
- */
-TEST(CollationTest, FailBadAttributionNodePosition) {
-    Atoms atoms;
-    int errorCount =
-            collate_atoms(BadAttributionNodePosition::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(1, errorCount);
-}
-
-TEST(CollationTest, FailOnBadStateAtomOptions) {
-    Atoms atoms;
-    int errorCount = collate_atoms(BadStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(3, errorCount);
-}
-
-TEST(CollationTest, PassOnGoodStateAtomOptions) {
-    Atoms atoms;
-    int errorCount = collate_atoms(GoodStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-    EXPECT_EQ(0, errorCount);
-}
-
-TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
-    Atoms atoms;
-    int errorCount =
-            collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-    EXPECT_EQ(0, errorCount);
-}
-
-TEST(CollationTest, FailOnBadBinaryFieldAtom) {
-    Atoms atoms;
-    int errorCount =
-            collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-    EXPECT_GT(errorCount, 0);
-}
-
-TEST(CollationTest, PassOnLogFromModuleAtom) {
-    Atoms atoms;
-    int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-    EXPECT_EQ(errorCount, 0);
-    EXPECT_EQ(atoms.decls.size(), 4ul);
-}
-
-TEST(CollationTest, RecognizeModuleAtom) {
-    Atoms atoms;
-    int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-    EXPECT_EQ(errorCount, 0);
-    EXPECT_EQ(atoms.decls.size(), 4ul);
-    EXPECT_EQ(atoms.signatureInfoMap.size(), 2u);
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING);
-
-    SignatureInfoMap::const_iterator signatureInfoMapIt;
-    const vector<java_type_t>* signature;
-    const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
-    FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
-    const AtomDeclSet* atomDeclSet;
-    AtomDeclSet::const_iterator atomDeclSetIt;
-    AtomDecl* atomDecl;
-    FieldNumberToAnnotations* fieldNumberToAnnotations;
-    FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
-    const AnnotationSet* annotationSet;
-    AnnotationSet::const_iterator annotationSetIt;
-    Annotation* annotation;
-
-    signatureInfoMapIt = atoms.signatureInfoMap.begin();
-    signature = &(signatureInfoMapIt->first);
-    fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
-    EXPECT_EQ(1ul, signature->size());
-    EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
-    EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
-    fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
-    EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
-    atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
-    EXPECT_EQ(2ul, atomDeclSet->size());
-    atomDeclSetIt = atomDeclSet->begin();
-    atomDecl = atomDeclSetIt->get();
-    EXPECT_EQ(1, atomDecl->code);
-    fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
-    fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
-    EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
-    annotationSet = &fieldNumberToAnnotationsIt->second;
-    EXPECT_EQ(1ul, annotationSet->size());
-    annotationSetIt = annotationSet->begin();
-    annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
-    EXPECT_EQ(1, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
-    EXPECT_TRUE(annotation->value.boolValue);
-
-    atomDeclSetIt++;
-    atomDecl = atomDeclSetIt->get();
-    EXPECT_EQ(3, atomDecl->code);
-    fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
-    fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
-    EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
-    annotationSet = &fieldNumberToAnnotationsIt->second;
-    EXPECT_EQ(1ul, annotationSet->size());
-    annotationSetIt = annotationSet->begin();
-    annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
-    EXPECT_EQ(3, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
-    EXPECT_TRUE(annotation->value.boolValue);
-
-    signatureInfoMapIt++;
-    signature = &signatureInfoMapIt->first;
-    fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
-    EXPECT_EQ(1ul, signature->size());
-    EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0));
-    EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size());
-}
-
-TEST(CollationTest, RecognizeModule1Atom) {
-    Atoms atoms;
-    const string moduleName = "module1";
-    int errorCount = collate_atoms(ModuleAtoms::descriptor(), moduleName, &atoms);
-    EXPECT_EQ(errorCount, 0);
-    EXPECT_EQ(atoms.decls.size(), 2ul);
-    EXPECT_EQ(atoms.signatureInfoMap.size(), 1u);
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
-    SignatureInfoMap::const_iterator signatureInfoMapIt;
-    const vector<java_type_t>* signature;
-    const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
-    FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
-    const AtomDeclSet* atomDeclSet;
-    AtomDeclSet::const_iterator atomDeclSetIt;
-    AtomDecl* atomDecl;
-    FieldNumberToAnnotations* fieldNumberToAnnotations;
-    FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
-    const AnnotationSet* annotationSet;
-    AnnotationSet::const_iterator annotationSetIt;
-    Annotation* annotation;
-
-    signatureInfoMapIt = atoms.signatureInfoMap.begin();
-    signature = &(signatureInfoMapIt->first);
-    fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
-    EXPECT_EQ(1ul, signature->size());
-    EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
-    EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
-    fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
-    EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
-    atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
-    EXPECT_EQ(2ul, atomDeclSet->size());
-    atomDeclSetIt = atomDeclSet->begin();
-    atomDecl = atomDeclSetIt->get();
-    EXPECT_EQ(1, atomDecl->code);
-    fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
-    fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
-    EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
-    annotationSet = &fieldNumberToAnnotationsIt->second;
-    EXPECT_EQ(1ul, annotationSet->size());
-    annotationSetIt = annotationSet->begin();
-    annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
-    EXPECT_EQ(1, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
-    EXPECT_TRUE(annotation->value.boolValue);
-
-    atomDeclSetIt++;
-    atomDecl = atomDeclSetIt->get();
-    EXPECT_EQ(3, atomDecl->code);
-    fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
-    fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
-    EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
-    annotationSet = &fieldNumberToAnnotationsIt->second;
-    EXPECT_EQ(1ul, annotationSet->size());
-    annotationSetIt = annotationSet->begin();
-    annotation = annotationSetIt->get();
-    EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
-    EXPECT_EQ(3, annotation->atomId);
-    EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
-    EXPECT_TRUE(annotation->value.boolValue);
-}
-
-/**
- * Test that an atom is not a pushed nor pulled atom.
- */
-TEST(CollationTest, InvalidAtomType) {
-    Atoms atoms;
-    int errorCount = collate_atoms(NotAPushNorPullAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that an atom was not declared in a `oneof` field.
- */
-TEST(CollationTest, AtomNotDeclaredInAOneof) {
-    Atoms atoms;
-    int errorCount = collate_atoms(AtomNotInAOneof::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test a correct collation with pushed and pulled atoms.
- */
-TEST(CollationTest, CollatePushedAndPulledAtoms) {
-    Atoms atoms;
-    int errorCount = collate_atoms(PushedAndPulledAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
-    EXPECT_EQ(0, errorCount);
-    EXPECT_EQ(1ul, atoms.signatureInfoMap.size());
-    EXPECT_EQ(2ul, atoms.pulledAtomsSignatureInfoMap.size());
-
-    // IntAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
-    // AnotherIntAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT);
-
-    // OutOfOrderAtom
-    EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
-
-    EXPECT_EQ(3ul, atoms.decls.size());
-
-    AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
-    EXPECT_EQ(1, (*atomIt)->code);
-    EXPECT_EQ("int_atom_1", (*atomIt)->name);
-    EXPECT_EQ("IntAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(10, (*atomIt)->code);
-    EXPECT_EQ("another_int_atom", (*atomIt)->name);
-    EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(11, (*atomIt)->code);
-    EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
-    EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
-    EXPECT_NO_ENUM_FIELD((*atomIt));
-    atomIt++;
-
-    EXPECT_EQ(atoms.decls.end(), atomIt);
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
deleted file mode 100644
index 1eaf42a..0000000
--- a/tools/stats_log_api_gen/utils.cpp
+++ /dev/null
@@ -1,467 +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.
- */
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-/**
- * Inlining this method because "android-base/strings.h" is not available on
- * google3.
- */
-static vector<string> Split(const string& s, const string& delimiters) {
-    GOOGLE_CHECK_NE(delimiters.size(), 0U);
-
-    vector<string> result;
-
-    size_t base = 0;
-    size_t found;
-    while (true) {
-        found = s.find_first_of(delimiters, base);
-        result.push_back(s.substr(base, found - base));
-        if (found == s.npos) break;
-        base = found + 1;
-    }
-
-    return result;
-}
-
-static void build_non_chained_decl_map(const Atoms& atoms,
-                                       std::map<int, AtomDeclSet::const_iterator>* decl_map) {
-    for (AtomDeclSet::const_iterator atomIt = atoms.non_chained_decls.begin();
-         atomIt != atoms.non_chained_decls.end(); atomIt++) {
-        decl_map->insert(std::make_pair((*atomIt)->code, atomIt));
-    }
-}
-
-const map<AnnotationId, string>& get_annotation_id_constants() {
-    static const map<AnnotationId, string>* ANNOTATION_ID_CONSTANTS =
-        new map<AnnotationId, string>{
-            {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
-            {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
-            {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
-            {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
-            {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
-            {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
-            {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
-
-    return *ANNOTATION_ID_CONSTANTS;
-}
-
-/**
- * Turn lower and camel case into upper case with underscores.
- */
-string make_constant_name(const string& str) {
-    string result;
-    const int N = str.size();
-    bool underscore_next = false;
-    for (int i = 0; i < N; i++) {
-        char c = str[i];
-        if (c >= 'A' && c <= 'Z') {
-            if (underscore_next) {
-                result += '_';
-                underscore_next = false;
-            }
-        } else if (c >= 'a' && c <= 'z') {
-            c = 'A' + c - 'a';
-            underscore_next = true;
-        } else if (c == '_') {
-            underscore_next = false;
-        }
-        result += c;
-    }
-    return result;
-}
-
-const char* cpp_type_name(java_type_t type) {
-    switch (type) {
-        case JAVA_TYPE_BOOLEAN:
-            return "bool";
-        case JAVA_TYPE_INT:
-        case JAVA_TYPE_ENUM:
-            return "int32_t";
-        case JAVA_TYPE_LONG:
-            return "int64_t";
-        case JAVA_TYPE_FLOAT:
-            return "float";
-        case JAVA_TYPE_DOUBLE:
-            return "double";
-        case JAVA_TYPE_STRING:
-            return "char const*";
-        case JAVA_TYPE_BYTE_ARRAY:
-            return "const BytesField&";
-        default:
-            return "UNKNOWN";
-    }
-}
-
-const char* java_type_name(java_type_t type) {
-    switch (type) {
-        case JAVA_TYPE_BOOLEAN:
-            return "boolean";
-        case JAVA_TYPE_INT:
-        case JAVA_TYPE_ENUM:
-            return "int";
-        case JAVA_TYPE_LONG:
-            return "long";
-        case JAVA_TYPE_FLOAT:
-            return "float";
-        case JAVA_TYPE_DOUBLE:
-            return "double";
-        case JAVA_TYPE_STRING:
-            return "java.lang.String";
-        case JAVA_TYPE_BYTE_ARRAY:
-            return "byte[]";
-        default:
-            return "UNKNOWN";
-    }
-}
-
-// Native
-// Writes namespaces for the cpp and header files, returning the number of
-// namespaces written.
-void write_namespace(FILE* out, const string& cppNamespaces) {
-    vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
-    for (const string& cppNamespace : cppNamespaceVec) {
-        fprintf(out, "namespace %s {\n", cppNamespace.c_str());
-    }
-}
-
-// Writes namespace closing brackets for cpp and header files.
-void write_closing_namespace(FILE* out, const string& cppNamespaces) {
-    vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
-    for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
-        fprintf(out, "} // namespace %s\n", it->c_str());
-    }
-}
-
-static void write_cpp_usage(FILE* out, const string& method_name, const string& atom_code_name,
-                            const shared_ptr<AtomDecl> atom, const AtomDecl& attributionDecl) {
-    fprintf(out, "     * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
-
-    for (vector<AtomField>::const_iterator field = atom->fields.begin();
-         field != atom->fields.end(); field++) {
-        if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            for (const auto& chainField : attributionDecl.fields) {
-                if (chainField.javaType == JAVA_TYPE_STRING) {
-                    fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
-                            chainField.name.c_str());
-                } else {
-                    fprintf(out, ", const %s* %s, size_t %s_length",
-                            cpp_type_name(chainField.javaType), chainField.name.c_str(),
-                            chainField.name.c_str());
-                }
-            }
-        } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out,
-                    ", const std::map<int, int32_t>& %s_int"
-                    ", const std::map<int, int64_t>& %s_long"
-                    ", const std::map<int, char const*>& %s_str"
-                    ", const std::map<int, float>& %s_float",
-                    field->name.c_str(), field->name.c_str(), field->name.c_str(),
-                    field->name.c_str());
-        } else {
-            fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
-        }
-    }
-    fprintf(out, ");\n");
-}
-
-void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl) {
-    fprintf(out, "/**\n");
-    fprintf(out, " * Constants for atom codes.\n");
-    fprintf(out, " */\n");
-    fprintf(out, "enum {\n");
-
-    std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
-    build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
-    size_t i = 0;
-    // Print atom constants
-    for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
-         atomIt++) {
-        string constant = make_constant_name((*atomIt)->name);
-        fprintf(out, "\n");
-        fprintf(out, "    /**\n");
-        fprintf(out, "     * %s %s\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
-        write_cpp_usage(out, "stats_write", constant, *atomIt, attributionDecl);
-
-        auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
-        if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
-            write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
-                            attributionDecl);
-        }
-        fprintf(out, "     */\n");
-        char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
-        fprintf(out, "    %s = %d%s\n", constant.c_str(), (*atomIt)->code, comma);
-        i++;
-    }
-    fprintf(out, "\n");
-    fprintf(out, "};\n");
-    fprintf(out, "\n");
-}
-
-void write_native_method_signature(FILE* out, const string& signaturePrefix,
-                                   const vector<java_type_t>& signature,
-                                   const AtomDecl& attributionDecl, const string& closer) {
-    fprintf(out, "%sint32_t code", signaturePrefix.c_str());
-    int argIndex = 1;
-    for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-         arg++) {
-        if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            for (const auto& chainField : attributionDecl.fields) {
-                if (chainField.javaType == JAVA_TYPE_STRING) {
-                    fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
-                            chainField.name.c_str());
-                } else {
-                    fprintf(out, ", const %s* %s, size_t %s_length",
-                            cpp_type_name(chainField.javaType), chainField.name.c_str(),
-                            chainField.name.c_str());
-                }
-            }
-        } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out,
-                    ", const std::map<int, int32_t>& arg%d_1, "
-                    "const std::map<int, int64_t>& arg%d_2, "
-                    "const std::map<int, char const*>& arg%d_3, "
-                    "const std::map<int, float>& arg%d_4",
-                    argIndex, argIndex, argIndex, argIndex);
-        } else {
-            fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
-        }
-        argIndex++;
-    }
-    fprintf(out, ")%s\n", closer.c_str());
-}
-
-void write_native_method_call(FILE* out, const string& methodName,
-                              const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
-                              int argIndex) {
-    fprintf(out, "%s(code", methodName.c_str());
-    for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-         arg++) {
-        if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            for (const auto& chainField : attributionDecl.fields) {
-                if (chainField.javaType == JAVA_TYPE_STRING) {
-                    fprintf(out, ", %s", chainField.name.c_str());
-                } else {
-                    fprintf(out, ",  %s,  %s_length", chainField.name.c_str(),
-                            chainField.name.c_str());
-                }
-            }
-        } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex, argIndex, argIndex,
-                    argIndex);
-        } else {
-            fprintf(out, ", arg%d", argIndex);
-        }
-        argIndex++;
-    }
-    fprintf(out, ");\n");
-}
-
-// Java
-void write_java_atom_codes(FILE* out, const Atoms& atoms) {
-    fprintf(out, "    // Constants for atom codes.\n");
-
-    std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
-    build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
-    // Print constants for the atom codes.
-    for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
-         atomIt++) {
-        string constant = make_constant_name((*atomIt)->name);
-        fprintf(out, "\n");
-        fprintf(out, "    /**\n");
-        fprintf(out, "     * %s %s<br>\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
-        write_java_usage(out, "write", constant, **atomIt);
-        auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
-        if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
-            write_java_usage(out, "write_non_chained", constant, **(non_chained_decl->second));
-        }
-        fprintf(out, "     */\n");
-        fprintf(out, "    public static final int %s = %d;\n", constant.c_str(), (*atomIt)->code);
-    }
-    fprintf(out, "\n");
-}
-
-void write_java_enum_values(FILE* out, const Atoms& atoms) {
-    fprintf(out, "    // Constants for enum values.\n\n");
-    for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
-         atomIt++) {
-        for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
-             field != (*atomIt)->fields.end(); field++) {
-            if (field->javaType == JAVA_TYPE_ENUM) {
-                fprintf(out, "    // Values for %s.%s\n", (*atomIt)->message.c_str(),
-                        field->name.c_str());
-                for (map<int, string>::const_iterator value = field->enumValues.begin();
-                     value != field->enumValues.end(); value++) {
-                    fprintf(out, "    public static final int %s__%s__%s = %d;\n",
-                            make_constant_name((*atomIt)->message).c_str(),
-                            make_constant_name(field->name).c_str(),
-                            make_constant_name(value->second).c_str(), value->first);
-                }
-                fprintf(out, "\n");
-            }
-        }
-    }
-}
-
-void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
-                      const AtomDecl& atom) {
-    fprintf(out, "     * Usage: StatsLog.%s(StatsLog.%s", method_name.c_str(),
-            atom_code_name.c_str());
-    for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end();
-         field++) {
-        if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-            fprintf(out, ", android.os.WorkSource workSource");
-        } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
-            fprintf(out, ", android.util.SparseArray<Object> value_map");
-        } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
-            fprintf(out, ", byte[] %s", field->name.c_str());
-        } else {
-            fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
-        }
-    }
-    fprintf(out, ");<br>\n");
-}
-
-int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        // Print method signature.
-        fprintf(out, "    public static void write_non_chained(int code");
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-        int argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                fprintf(stderr, "Non chained signatures should not have attribution chains.\n");
-                return 1;
-            } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(stderr, "Module logging does not yet support key value pair.\n");
-                return 1;
-            } else {
-                fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ") {\n");
-
-        fprintf(out, "        write(code");
-        argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            // First two args are uid and tag of attribution chain.
-            if (argIndex == 1) {
-                fprintf(out, ", new int[] {arg%d}", argIndex);
-            } else if (argIndex == 2) {
-                fprintf(out, ", new java.lang.String[] {arg%d}", argIndex);
-            } else {
-                fprintf(out, ", arg%d", argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ");\n");
-        fprintf(out, "    }\n");
-        fprintf(out, "\n");
-    }
-    return 0;
-}
-
-int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
-    fprintf(out, "    // WorkSource methods.\n");
-    for (auto signatureInfoMapIt = signatureInfoMap.begin();
-         signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        vector<java_type_t> signature = signatureInfoMapIt->first;
-        // Determine if there is Attribution in this signature.
-        int attributionArg = -1;
-        int argIndexMax = 0;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            argIndexMax++;
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                if (attributionArg > -1) {
-                    fprintf(stderr, "An atom contains multiple AttributionNode fields.\n");
-                    fprintf(stderr, "This is not supported. Aborting WorkSource method writing.\n");
-                    fprintf(out,
-                            "\n// Invalid for WorkSource: more than one attribution "
-                            "chain.\n");
-                    return 1;
-                }
-                attributionArg = argIndexMax;
-            }
-        }
-        if (attributionArg < 0) {
-            continue;
-        }
-
-        fprintf(out, "\n");
-        // Method header (signature)
-        fprintf(out, "    public static void write(int code");
-        int argIndex = 1;
-        for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
-             arg++) {
-            if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
-                fprintf(out, ", android.os.WorkSource ws");
-            } else {
-                fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
-            }
-            argIndex++;
-        }
-        fprintf(out, ") {\n");
-
-        // write_non_chained() component. TODO: Remove when flat uids are no longer
-        // needed.
-        fprintf(out, "        for (int i = 0; i < ws.size(); ++i) {\n");
-        fprintf(out, "            write_non_chained(code");
-        for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
-            if (argIndex == attributionArg) {
-                fprintf(out, ", ws.getUid(i), ws.getPackageName(i)");
-            } else {
-                fprintf(out, ", arg%d", argIndex);
-            }
-        }
-        fprintf(out, ");\n");
-        fprintf(out, "        }\n");  // close for-loop
-
-        // write() component.
-        fprintf(out,
-                "        java.util.List<android.os.WorkSource.WorkChain> workChains = "
-                "ws.getWorkChains();\n");
-        fprintf(out, "        if (workChains != null) {\n");
-        fprintf(out,
-                "            for (android.os.WorkSource.WorkChain wc : workChains) "
-                "{\n");
-        fprintf(out, "                write(code");
-        for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
-            if (argIndex == attributionArg) {
-                fprintf(out, ", wc.getUids(), wc.getTags()");
-            } else {
-                fprintf(out, ", arg%d", argIndex);
-            }
-        }
-        fprintf(out, ");\n");
-        fprintf(out, "            }\n");  // close for-loop
-        fprintf(out, "        }\n");      // close if
-        fprintf(out, "    }\n");          // close method
-    }
-    return 0;
-}
-
-}  // namespace stats_log_api_gen
-}  // namespace android
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
deleted file mode 100644
index 13a7e2d..0000000
--- a/tools/stats_log_api_gen/utils.h
+++ /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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_UTILS_H
-#define ANDROID_STATS_LOG_API_GEN_UTILS_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-const char DEFAULT_CPP_NAMESPACE[] = "android,util";
-const char DEFAULT_CPP_HEADER_IMPORT[] = "statslog.h";
-
-const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
-const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
-const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
-
-const map<AnnotationId, string>& get_annotation_id_constants();
-
-string make_constant_name(const string& str);
-
-const char* cpp_type_name(java_type_t type);
-
-const char* java_type_name(java_type_t type);
-
-// Common Native helpers
-void write_namespace(FILE* out, const string& cppNamespaces);
-
-void write_closing_namespace(FILE* out, const string& cppNamespaces);
-
-void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl);
-
-void write_native_method_signature(FILE* out, const string& signaturePrefix,
-                                   const vector<java_type_t>& signature,
-                                   const AtomDecl& attributionDecl, const string& closer);
-
-void write_native_method_call(FILE* out, const string& methodName,
-                              const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
-                              int argIndex = 1);
-
-// Common Java helpers.
-void write_java_atom_codes(FILE* out, const Atoms& atoms);
-
-void write_java_enum_values(FILE* out, const Atoms& atoms);
-
-void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
-                      const AtomDecl& atom);
-
-int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
-
-int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
-
-}  // namespace stats_log_api_gen
-}  // namespace android
-
-#endif  // ANDROID_STATS_LOG_API_GEN_UTILS_H
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index 4b0d38d..1ece79a 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -310,6 +310,7 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     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 @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean addSuggestionUserApprovalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener);
     method @Deprecated public static int calculateSignalLevel(int, int);
     method @IntRange(from=0) public int calculateSignalLevel(int);
     method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
@@ -360,6 +361,7 @@
     method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}) public void removePasspointConfiguration(String);
     method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionConnectionStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionUserApprovalStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener);
     method @Deprecated public boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -460,6 +462,10 @@
     method public void onConnectionStatus(@NonNull android.net.wifi.WifiNetworkSuggestion, int);
   }
 
+  public static interface WifiManager.SuggestionUserApprovalStatusListener {
+    method public void onUserApprovalStatusChange();
+  }
+
   public class WifiManager.WifiLock {
     method public void acquire();
     method public boolean isHeld();
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index e15d0f1..257f9d5 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -398,6 +398,8 @@
     method @Deprecated public boolean hasEverConnected();
     field @Deprecated public static final int DISABLED_ASSOCIATION_REJECTION = 1; // 0x1
     field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE = 2; // 0x2
+    field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10; // 0xa
+    field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2; // 0x2
     field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; // 0x5
     field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; // 0x9
     field @Deprecated public static final int DISABLED_BY_WIFI_MANAGER = 7; // 0x7
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index b15a8d7..2331c2f 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -21,6 +21,7 @@
 rule android.net.ResolverParamsParcel* com.android.wifi.x.@0
 rule android.net.RouteInfoParcel* com.android.wifi.x.@0
 rule android.net.ScanResultInfoParcelable* com.android.wifi.x.@0
+rule android.net.TcpKeepalivePacketDataParcelable* com.android.wifi.x.@0
 rule android.net.TetherConfigParcel* com.android.wifi.x.@0
 rule android.net.TetherOffloadRuleParcel* com.android.wifi.x.@0
 rule android.net.TetherStatsParcel* com.android.wifi.x.@0
@@ -43,7 +44,6 @@
 rule android.net.InterfaceConfiguration* com.android.wifi.x.@0
 rule android.net.IpMemoryStore* com.android.wifi.x.@0
 rule android.net.NetworkMonitorManager* com.android.wifi.x.@0
-rule android.net.TcpKeepalivePacketData* com.android.wifi.x.@0
 rule android.net.NetworkFactory* com.android.wifi.x.@0
 rule android.net.ip.IpClientCallbacks* com.android.wifi.x.@0
 rule android.net.ip.IpClientManager* com.android.wifi.x.@0
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
similarity index 65%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
copy to wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
index 23d86a0..5aa3a90 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 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,12 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.splitscreen;
+package android.net.wifi;
 
 /**
- * Class to hold state of divider that needs to persist across configuration changes.
+ * Interface for suggestion user approval status listener.
+ *
+ * @hide
  */
-final class DividerState {
-    public boolean animateAfterRecentsDrawn;
-    public float mRatioPositionBeforeMinimized;
+oneway interface ISuggestionUserApprovalStatusListener
+{
+   void onUserApprovalStatusChange();
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0d4e9c3..06ebee4 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -33,6 +33,7 @@
 import android.net.wifi.IScanResultsCallback;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ISuggestionConnectionStatusListener;
+import android.net.wifi.ISuggestionUserApprovalStatusListener;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.IWifiConnectedNetworkScorer;
 import android.net.wifi.ScanResult;
@@ -302,4 +303,8 @@
     boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged);
 
     void restartWifiSubsystem(String reason);
+
+    boolean addSuggestionUserApprovalStatusListener(in IBinder binder, in ISuggestionUserApprovalStatusListener listener, int listenerIdentifier, String packageName, String featureId);
+
+    void removeSuggestionUserApprovalStatusListener(int listenerIdentifier, String packageName);
 }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 2a98977..ba4a54f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1708,7 +1708,9 @@
                 DISABLED_NO_INTERNET_PERMANENT,
                 DISABLED_BY_WIFI_MANAGER,
                 DISABLED_BY_WRONG_PASSWORD,
-                DISABLED_AUTHENTICATION_NO_SUBSCRIPTION})
+                DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
+                DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+                DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC})
         public @interface NetworkSelectionDisableReason {}
 
         // Quality Network disabled reasons
@@ -1721,8 +1723,16 @@
         public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
         /** This network is temporarily disabled because of multiple association rejections. */
         public static final int DISABLED_ASSOCIATION_REJECTION = 1;
-        /** This network is temporarily disabled because of multiple authentication failure. */
-        public static final int DISABLED_AUTHENTICATION_FAILURE = 2;
+        /** This network is disabled due to generic authentication failure. */
+        public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2;
+        /** Separate DISABLED_AUTHENTICATION_FAILURE into DISABLED_AUTHENTICATION_FAILURE_GENERIC
+         *  and DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC
+         *  @deprecated Use the {@link #DISABLED_AUTHENTICATION_FAILURE_GENERIC} constant
+         * (which is the same value).
+         */
+        @Deprecated
+        public static final int DISABLED_AUTHENTICATION_FAILURE =
+                DISABLED_AUTHENTICATION_FAILURE_GENERIC;
         /** This network is temporarily disabled because of multiple DHCP failure. */
         public static final int DISABLED_DHCP_FAILURE = 3;
         /** This network is temporarily disabled because it has no Internet access. */
@@ -1740,11 +1750,13 @@
         public static final int DISABLED_BY_WRONG_PASSWORD = 8;
         /** This network is permanently disabled because service is not subscribed. */
         public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9;
+        /** This network is disabled due to carrier specific EAP failure. */
+        public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10;
         /**
          * All other disable reasons should be strictly less than this value.
          * @hide
          */
-        public static final int NETWORK_SELECTION_DISABLED_MAX = 10;
+        public static final int NETWORK_SELECTION_DISABLED_MAX = 11;
 
         /**
          * Get an integer that is equal to the maximum integer value of all the
@@ -1884,6 +1896,18 @@
                             1,
                             Integer.MAX_VALUE));
 
+            reasons.append(DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+                    new DisableReasonInfo(
+                            "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_GENERIC",
+                            5,
+                            5 * 60 * 1000));
+
+            reasons.append(DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC,
+                    new DisableReasonInfo(
+                            "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC",
+                            1,
+                            Integer.MAX_VALUE));
+
             return reasons;
         }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index bccb241..833f9b0 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -6892,4 +6892,95 @@
         }
     }
 
+    /**
+     * Interface for network suggestion user approval status change listener.
+     * Should be implemented by applications and registered using
+     * {@link #addSuggestionUserApprovalStatusListener(Executor,
+     * SuggestionUserApprovalStatusListener)} (
+     */
+    public interface SuggestionUserApprovalStatusListener {
+
+        /**
+         * Called when the user approval status of the App has changed. The current status can be
+         * queried by {@link #getNetworkSuggestionUserApprovalStatus()}
+         */
+        void onUserApprovalStatusChange();
+    }
+
+    private class SuggestionUserApprovalStatusListenerProxy extends
+            ISuggestionUserApprovalStatusListener.Stub {
+        private final Executor mExecutor;
+        private final SuggestionUserApprovalStatusListener mListener;
+
+        SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor,
+                @NonNull SuggestionUserApprovalStatusListener listener) {
+            mExecutor = executor;
+            mListener = listener;
+        }
+
+        @Override
+        public void onUserApprovalStatusChange() {
+            mExecutor.execute(() -> mListener.onUserApprovalStatusChange());
+        }
+
+    }
+
+    /**
+     * Add a listener for Wi-Fi network suggestion user approval status.
+     * See {@link SuggestionUserApprovalStatusListener}.
+     * Caller will receive a callback when the user approval status of the caller has changed.
+     * Caller can remove a previously registered listener using
+     * {@link WifiManager#removeSuggestionUserApprovalStatusListener(
+     * SuggestionUserApprovalStatusListener)}
+     * A caller can add multiple listeners to monitor the event.
+     * @param executor The executor to execute the listener of the {@code listener} object.
+     * @param listener listener for suggestion user approval status changes.
+     * @return true if succeed otherwise false.
+     */
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public boolean addSuggestionUserApprovalStatusListener(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SuggestionUserApprovalStatusListener listener) {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
+        if (executor == null) throw new IllegalArgumentException("Executor cannot be null");
+        Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener
+                + ", executor=" + executor);
+        try {
+            return mService.addSuggestionUserApprovalStatusListener(new Binder(),
+                    new SuggestionUserApprovalStatusListenerProxy(executor, listener),
+                    listener.hashCode(), mContext.getOpPackageName(), mContext.getAttributionTag());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+    }
+
+    /**
+     * Allow callers to remove a previously registered listener using
+     * {@link #addSuggestionUserApprovalStatusListener(Executor,
+     * SuggestionUserApprovalStatusListener)}. After calling this method,
+     * applications will no longer receive network suggestion user approval status change through
+     * that listener.
+     *
+     * @param listener listener to remove.
+     */
+    @RequiresPermission(ACCESS_WIFI_STATE)
+    public void removeSuggestionUserApprovalStatusListener(
+            @NonNull SuggestionUserApprovalStatusListener listener) {
+        if (!SdkLevel.isAtLeastS()) {
+            throw new UnsupportedOperationException();
+        }
+        if (listener == null) throw new IllegalArgumentException("Listener cannot be null");
+        Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener);
+        try {
+            mService.removeSuggestionUserApprovalStatusListener(listener.hashCode(),
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index bd56e5b..b15fa2c 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -89,6 +89,7 @@
 import android.net.wifi.WifiManager.ScanResultsCallback;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener;
+import android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener;
 import android.net.wifi.WifiManager.TrafficStateCallback;
 import android.net.wifi.WifiManager.WifiConnectedNetworkScorer;
 import android.os.Build;
@@ -148,12 +149,13 @@
     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
     @Mock OnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
-    @Mock SuggestionConnectionStatusListener mListener;
+    @Mock SuggestionConnectionStatusListener mSuggestionConnectionListener;
     @Mock Runnable mRunnable;
     @Mock Executor mExecutor;
     @Mock Executor mAnotherExecutor;
     @Mock ActivityManager mActivityManager;
     @Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
+    @Mock SuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener;
 
     private Handler mHandler;
     private TestLooper mLooper;
@@ -2354,7 +2356,7 @@
      */
     @Test(expected = IllegalArgumentException.class)
     public void testAddSuggestionConnectionStatusListenerWithNullExecutor() {
-        mWifiManager.addSuggestionConnectionStatusListener(null, mListener);
+        mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener);
     }
 
     /**
@@ -2374,11 +2376,12 @@
         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
         Executor executor = new SynchronousExecutor();
-        mWifiManager.addSuggestionConnectionStatusListener(executor, mListener);
+        mWifiManager.addSuggestionConnectionStatusListener(executor, mSuggestionConnectionListener);
         verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class),
                 callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
         callbackCaptor.getValue().onConnectionStatus(mWifiNetworkSuggestion, errorCode);
-        verify(mListener).onConnectionStatus(any(WifiNetworkSuggestion.class), eq(errorCode));
+        verify(mSuggestionConnectionListener).onConnectionStatus(any(WifiNetworkSuggestion.class),
+                eq(errorCode));
     }
 
     /**
@@ -2389,7 +2392,8 @@
         int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
-        mWifiManager.addSuggestionConnectionStatusListener(mExecutor, mListener);
+        mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
+                mSuggestionConnectionListener);
         verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class),
                 callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
         callbackCaptor.getValue().onConnectionStatus(any(WifiNetworkSuggestion.class), errorCode);
@@ -2409,7 +2413,7 @@
      */
     @Test
     public void testRemoveSuggestionConnectionListener() throws Exception {
-        mWifiManager.removeSuggestionConnectionStatusListener(mListener);
+        mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener);
         verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString());
     }
 
@@ -2636,4 +2640,84 @@
         verify(mWifiService).isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false);
     }
 
+
+    /**
+     * Verify an IllegalArgumentException is thrown if listener is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testRemoveSuggestionUserApprovalStatusListenerWithNullListener() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        mWifiManager.removeSuggestionUserApprovalStatusListener(null);
+    }
+
+
+    /**
+     * Verify removeSuggestionUserApprovalStatusListener.
+     */
+    @Test
+    public void testRemoveSuggestionUserApprovalStatusListener() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        mWifiManager.removeSuggestionUserApprovalStatusListener(
+                mSuggestionUserApprovalStatusListener);
+        verify(mWifiService).removeSuggestionUserApprovalStatusListener(anyInt(), anyString());
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if executor not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddSuggestionUserApprovalStatusListenerWithNullExecutor() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        mWifiManager.addSuggestionUserApprovalStatusListener(null,
+                mSuggestionUserApprovalStatusListener);
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if listener is not provided.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddSuggestionUserApprovalStatusListenerWithNullListener() {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, null);
+    }
+
+    /**
+     * Verify client provided listener is being called to the right listener.
+     */
+    @Test
+    public void testAddSuggestionUserApprovalStatusListenerAndReceiveEvent() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+
+        ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
+        Executor executor = new SynchronousExecutor();
+        mWifiManager.addSuggestionUserApprovalStatusListener(executor,
+                mSuggestionUserApprovalStatusListener);
+        verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
+        callbackCaptor.getValue().onUserApprovalStatusChange();
+        verify(mSuggestionUserApprovalStatusListener).onUserApprovalStatusChange();
+    }
+
+    /**
+     * Verify client provided listener is being called to the right executor.
+     */
+    @Test
+    public void testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()
+            throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
+        mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
+                mSuggestionUserApprovalStatusListener);
+        verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class),
+                callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class));
+        callbackCaptor.getValue().onUserApprovalStatusChange();
+        verify(mExecutor).execute(any(Runnable.class));
+    }
+
 }